Skip to main content

Full text of "Machine Language for the Commodore Revised and Expanded Edition"

See other formats


iiifiiiiiiiMm 

JIM BUTTERFIELD 

MACHINE LANGUAGE! 

FOR THE COMMODORE 64, 128, AND 




MACHINE 
LANGUAGE 
FOR THE 
COMMODORE 64, 128, 

and Other 
Commodore 
Computers 



Jim Butterfield 

A Brady Book 
Published by Prentice IHall Press 
New Yorl<, New York 10023 



Machine Language for the Commodore 64, 128, and Other 
Commodore Computers 

Copyright © 1986 by Brady Communications Company, Inc. 

All rights reserved 

Including the right of reproduction 

In whole or in part in any fonn 

A Brady Book 

Published by Prentice l-iall Press 
A Division of Simon & Schuster, Inc. 
Gulf + Western Building 
One Gulf + Westem Plaza 
New York, New York 10023 

PRENTICE HALL PRESS is a trademark of Simon & Schuster, Inc. 
Manufactured in the United States of^merica 
123456789 10 

Library of Congress Cataloging in Pubiication Data 

Butterfield, Jim 

Machine language for the Commodore 64, 128, and 
other Commodore computers 

Includes index. 

1. Commodore 64 (Computer) — Programming. 2. Commodore 
computers— Programming. 3. Programming languages 
(Electronic computers) I. Title. 

QA76.8.C64B88 1986 001.64'2 84-6351 



ISBN D-flRBDa-bBa-fl 



Contents 



Note to Readers 

Preface 

Introduction 

1 First Concepts 



vii 
ix 
xiii 



1 



The Inner Workings of Microcomputers 

l\^emory Elements 

Microprocessor Registers 

Instruction Execution 

First Program Project 

Monitors: What They Are 

The Machine Language Monitor 

MLM Commands 

Changing Memory Contents 

Changing Registers 

Entering the Program 

Things You Have Learned 

Detail: Program Execution 

Questions and Projects 

2 Controlling Output 23 

Calling Machine Language Subroutines 

CHROUT— The Output Subroutine 

Why Not POKE? 

A Print Project 

Monitor Extensions 

Checking: The Disassembler 

Running the Program 

Linking with BASIC 

Loops 

Things You Have Learned 
Questions and Projects 



ill 



3 Flags, Logic, and Input 39 

Flags 

A Brief Diversion: Signed Numbers 

A Brief Diversion: Overflow 

Flag Summary 

The Status Register 

Instructions: A Review 

Logical Operators 

Why Logical Operations? 

Input: The GETIN Subroutine 

STOP 

Programming Project 
Things You Have Learned 
Questions and Projects 



4 Numbers, Arithmetic, and Subroutines 57 

Numbers: Signed and Unsigned 

Big Numbers: Multiple Bytes 

Addition 

Subtraction 

Comparing Numbers 

Multiplication 

Subroutines 

The Project 

Things You Have Learned 
Questions and Projects 

5 Address Ixodes 71 

Addressing Modes 

No Address: Implied Mode 

No Address: Accumulator Mode 

Not Quite an Address: Immediate Mode 

A Single Address: Absolute Mode 

Zero-Page Mode 

A Range of 256 Addresses: Absolute, Indexed Mode 
All of Zero Page: Zero-Page, Indexed 
Branching: Relative Address Mode 



iv 



Data From Anywhere: Indirect, Indexed 

A Rarity: Indexed, Indirect 

Project: Screen Manipulation 

Comment for VIC-20 and Commodore 64 

Things You Have Learned 

Questions and Projects 

6 Linking BASIC and IVIachine Language 91 

Siting the Program 
BASIC Memory Layout 
The Wicl<ed SOV 
BASIC N^afiables 

Exchanging Data: BASIC and Machine Language 
Things You Have Learned 
Questions and Projects 

7 Staci(, USR, interrufJt, atld Wedge 111 

A Brief Intermission 
Temporary Storage: The Stack 
Interrupts and RTI 
USR: A Brother to SYS 
Interrupts: NMI, IRQ, and BRK 
An Interrupt Project 
The lA Chips: PIA, VIA, and CIA 
Infiltrating BASIC: The Wedge 
Project: Adding a Command 
Things You Have Learned 
Questions and Projects 

8 Timing, Input/Output, and Conclusion 131 

Timing 

Input and Output 

A File Transfer Program 

Review: The Instruction Set 

Debugging 

Symbolic Assemblers 
What You Have Learned 
Questions and Projects 



V 



Appendix A 


The 6502/6510/6509/7501/8500 instruction 


147 


Set 


Appendix B 


Some Characteristics of Commodore 


155 


Machines 

IWlCiwI III Iww 


Mppenaix w 


Moinnrv Mans 


167 


MppenijiA u 


Oharflct^r Sets 


241 


Appenaix c 


Fvorri^efi for Alternative Commodore 


251 


il/iachines 


AoDendix F 


Floating Point Representation 


277 


Appendix G 


Uncrashing 


279 


Appendix H 


Supermon Instructions 


283 


Appendix 1 


lA Chip Information 


293 


Appendix J 


Disk User's Guide 


357 


Glossary 




365 


index 




371 



vi 



Note to Readers 

This book introduces beginners to the principles of machine language: what it 
is, how it works, and how to program with it. 

It is based on an intensive two-day course on machine language that has been 
presented many times over the past five years. 

Readers of this book should have a computer on hand: students will learn by 
doing, not just by reading. Upon completing the tutorial material in this book, the 
reader will have a good idea of the fundamentals of machine language. There will 
be more to be learned; but by this time, students should understand how to adapt 
other material from books and magazines to their own particular computers. 

LIMITS OF LIABILITY AND 
DISCLAIMER OF WARRANTY 

The author and publisher of this book have used their best efforts in preparing 
this book and the programs contained in it. These efforts include the development, 
research, and testing of the programs to determine their effectiveness. The author 
and the publisher make no warranty of any kind, expressed or implied, with regard 
to these programs, the text, or the documentation contained in this book. The 
author and the publisher shall not be liable in any event for claims of incidental 
or consequential damages in connection with, or arising out of, the furnishing, 
performance, or use of the text or the programs. 

Note for Commodore 128 Owners 

The Commodore 1 28 is three machines in one: a Commodore 64, a Commodore 
128, and a CP/M machine. You may select any of the three at any time. 

If you choose the Commodore 64 mode, you'll find examples within this book 
that will work on your machine. The programs you write will be compatible with 
other ("real") Commodore 64 computers. But you'll lose access to extra memory 
and to other features of the new machine. In particular, you won't have a built-in 
machine language monitor and will need to load one from tape or disk. 

If you choose the Commodore 128 mode, you're working with a richer and more 
powerful machine. You will have a built-in machine language monitor for speed 
and convenience, and access to new features such as 80 columns, with extra 
complexity. There are new rules to be learned. This book contains extra material 
to enable you to cope with the new features of the CI 28. 

If you choose CP/M mode, you will be in an environment that is quite different 
from other Commodore machines. This book, working with the 64 or 1 28 mode, 
can teach you principleis of machine language and skills which may be carried to 
other computer environments, including CP/M. But it will not teach you CP/M itself 
or CP/M's machine language. 



vii 



A Commodore 128 owner can read each chapter of this book twice, if desired. 
The first time, the exercises for the Commodore 64 can be worl<ed through; the 
second time, those for the 128 can be used. The principles are the same; the 
code is similar; but the 128 often calls for a little more detailed worl<. 

If you wish to learn machine language for the Commodore 128, please read the 
Introduction in Appendix E, under Exercises for the Commodore 128. It will give 
you some starting facts about your machine. There is more information on the 
128 in the latter section of Appendix B and elsewhere, but don't try to read it all 
at the start. It will be there when you need it. 



viii 



Preface 

This book is primariiy tutorial in nature. It contains, however, extensive reference 
material, which the reader will want to continue to use. 

No previous machine language experience is required. It is useful if the reader 
has had some background in programming in other languages, so that concepts 
such as loops and decisions are understood. 

Beginners will find that the material in this book moves at a fast pace. Stay with 
it; if necessary, skip ahead to the examples and then come back to reread a difficult 
area. 

Readers with some machine language experience may find some of the material 
too easy; for example, they are probably quite familiar with hexadecimal notation 
and don't need to read that part. If this is the case, skip ahead. But do enter all 
the programming projects; if you have missed a point, you may spot it while doing 
an exercise. 

Programming students learn by doing. The beginner needs to learn simple things 
about his or her machine in order to feel in control. The elements that are needed 
may be itemized as: 

• Machine language. This is the objective, but you can't get there without the 
next two items. 

• Machine architecture. All the machine language theory in the world will have 
little meaning unless the student knows such things as where a program may 
be placed in memory, how to print to the screen, or how to input from the 
keyboard. 

• Machine language tools. The use of a simple machine language monitor to 
read and change memory is vital to the objective of making the computer do 
something in machine language. Use of a simple assembler and elements of 
debugging are easy once you know them; but until you know them, it's hard 
to make the machine do anything. 

Principles of sound coding are important. They are seldom discussed explicitly, 
but run as an undercurrent through the material. The objective is this: it's easy to 
do things the right way, and more difficult to do them the wrong way. By introducing 
examples of good coding practices early, the student will not be motivated to look 
for a harder (and inferior) way of coding. 

It should be pointed out that this book deals primarily with machine language, 
not assembly language. Assembler programs are marvellous things, but they are 

ix 



too advanced for the beginner. I prefer to see the student forming an idea of how 
the bytes of the program lie within memory. After this concept is firmly fixed in 
mind, he or she can then look to the greater power and flexibility offered by an 
assembler. 



X 



Acknowledgements 

Thanks go to Elizabeth Deal for acting as resource person in the preparation 
of this book. When I was hard to find, the publisher could call upon Elizabeth for 
technical clarification. 



xi 



Introduction 

Why learn machine language? There are three reasons. First, for speed; ma- 
chine language programs are fast. Second, for versatility; all other languages are 
limited in some way, but not machine language. Third, for comprehension; since 
the computer really works in machine language only, the key to understanding 
how the machine operates is machine language. 

Is it hard? Not really. It's finicky, but not difficult. Individual machine language 
instructions don't do much, so we need many of them to do a job. But each 
instruction is simple, and anyone can understand it if he or she has the patience. 

Some programmers who started their careers in machine language find "higher 
level" languages such as BASIC quite difficult by comparison. To them, machine 
language instructions are simple and precise, whereas BASIC statements seem 
vague and poorly defined by comparison. 

Where will this book take you? You will end up with a good understanding of 
what machine language is, and the principles of how to program in it. You won't 
be an expert, but you'll have a good start and will no longer be frightened by this 
seemingly mysterious language. 

Will the skills you learn be transportable to other machines? Certainly. Once 
you understand the principles of programming, you'll be able to adapt. If you were 
to change to a non-Commodore machine that used the 6502 chip (such as Apple 
or Atari), you'd need to learn about the architecture of these machines and about 
their machine language monitors. They would be different, but the same principles 
would apply on all of them. 

Even if you change to a computer that doesn't use a chip from the 6502 family, 
you will be able to adapt. As you pick through the instructions and bits of the 
Commodore machine, you will have learned about the principles of all binary 
computers. You will need to learn the new microprocessor's instruction set, but it 
will be much easier the second time around. 

Do you need to be a BASIC expert before tackling machine language? Not at 
all. This book assumes you know a little about programming fundamentals: loops, 
branching, subroutines, and decision making. But you don't need to be an ad- 
vanced programmer to learn machine language. 



xiii 



1 



First 
Concepts 

This cliapter discusses: 

• Tile inner worl<ings of microcomputers 

• Computer notation: binary and hexadecimal 

• The 650x's inner architecture 

• Beginning use of a machine language monitor 

• A computer's "memory layout" 

• First machine language commands 

• Writing and entering a simple program 



1 



2 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



The Inner Workings of Microcomputers 

All computers contain a large number of electrical circuits. Within any 
binary computer, these circuits may be in only two states: "on" or "off." 

Technicians will tell you that "on" usually means full voltage on the circuit 
concerned, and "off" means no voltage. There's no need for volume control 
adjustments within a digital computer: each circuit is either fully on or fully 
off. 

The word "binary" means "based on two," and everything that happens 
within the computer is based on the two possibilities of each circuit: on or 
off. We can identify these two conditions in any of several ways: 

ON or OFF 
TRUE or FALSE 
YES or NO 
1 orO 

The last description, 1 or 0, is quite useful. It is compact and numeric. If 
we had a group of eight circuits within the computer, some of which were 
"on" and others "off," we could describe their conditions with an expression 
such as: 

llDDDlll 

This would signify that the two leftmost wires were on, the next three off, 
and the remaining three on. The value 11000111 looks like a number; in 
fact, it is a binary number in which each digit is or 1 . It should not be 
confused with the equivalent decimal value of slightly over 1 1 million; the 
digits would look the same, but in decimal each digit could have a value 
from to 9. To avoid confusion with decimal numbers, binary numbers 
are often preceded by a percent sign, so that the number might be shown 
as ^liiaODlll . 

Each digit of a binary number is called a bit, which is short for "binary 
digit." The number shown above has eight bits; a group of eight bits is a 
byte. Bits are often numbered from the right, starting at zero. The right- 
hand bit of the above number would be called "bit 0," and the left-hand 
bit would be called "bit 7." This may seem odd, but there's a good math- 
ematical reason for using such a numbering scheme. 



FIRST CONCEPTS 



3 



The Bus 

It's fairly common for a group of circuits to be used together. The wires 
run from one microchip to another, and then on to the next. Where a group 
of wires are used together and connect to several different points, the 
group is called a bus (sometimes spelled "buss"). 

The PET, CBM, and VIC-20 use a microprocessor chip called the 6502. 
The Commodore 64 uses a 6510. The Commodore B series uses a 6509 
chip, and the Commodore PLUS/4 uses a chip called 7501 . All these chips 
are similar, and there are other chips in the same family with numbers like 
6504; every one works on the same principles, and we'll refer to all of 
them by the family name 650x. 

Let's take an example of a bus used on any 650x chip. A 650x chip has 
little built-in storage. To get an instruction or perform a computation, the 
650x must call up information from "memory"— data stored within other 
chips. 

The 650x sends out a "call" to all memory chips, asking for information. 
It does this by sending out voltages on a group of sixteen wires called the 
"address bus." Each of the sixteen wires may carry either voltage or no 
voltage; this combination of signals is called an address. 

Every memory chip is connected to the address bus. Each chip reads the 
address, the combination of voltages sent by the processor. One and only 
one chip says, "That's me!" In other words, the specific address causes 













650x 










































































1 






1 1 1 




\ 






1 1 1 




1 








1 1 1 








MEMORY 
CHIP 




MEMORY 







Figure 1.1 Address bus connecting 650x & 3 chips 



4 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



that chip to be selected; it prepares to communicate with the 650x. All 
other chips say, "That's not me!" and will not participate in data transfer. 



The Data Bus 

Once the 650x microprocessor has sent an address over the address bus 
and it has been recognized by a memory chip, data may flow between 
memory and 650x. This data is eight bits (it flows over eight wires). It 
might look like this: 

□IDllDll 

The data might flow either way. That is, the 650x might read from the 
memory chip, in which case the selected memory chip places information 
onto the data bus which is read by the microprocessor. Alternatively, the 
650x might wish to write to the memory chip. In this case, the 650x places 
information onto the data bus, and the selected memory chip receives the 
data and stores it. 



650x 



-ADDRESS BUS- 



DATA BUS 



III 



MEMORY 
CHIP 
("SELECTED") 



MEMORY 

CHIP 

(NOT 
SELECTED) 



MEMORY 

CHIP 

(NOT 
SELECTED) 



Figure 1.2 Two-way data bus 

All other chips are still connected to the data bus, but they have not been 
selected, so they ignore the information. 

The address bus is accompanied by a few extra wires (sometimes called 



FIRST CONCEPTS 



5 



the control bus) that control such things as data timing and the direction 
in which the data should flow: read or write. 

Number Ranges 

The address bus has sixteen bits, each of which might be on or off. The 
possible combinations number 65536 (two raised to the sixteenth power). 
We then have 65536 different possibilities of voltages, or 65536 different 
addresses. 

The data bus has eight bits, which allows for 256 possibilities of voltages. 
Each memory location can store only 256 distinct values. 

It is often convenient to refer to an address as a decimal number. This is 
especially true for PEEK and POKE statements in the BASIC language. 
We may do this by giving each bit a "weight." Bit zero (at the right) has 
a weight of 1; each bit to the left has a weight of double the amount, so 
that bit 15 (at the left) has a weight of 32768. Thus, a binary address such 
as 

□DDIODIOIDIDIIDD 

has a value of 4096 + 512 + 128 + 32 + 8 + 4 or 4780. A POKE to 4780 
decimal would use the above binary address to reach the correct part of 
memory. 



128 


64 


32 


16 


8 


4 


2 


1 



EIGHT BITS 



32768 


16384 


8192 


4096 


2048 


1024 


512 


256 


777-. 
128 


64 


^77 

32 


16 


7 

8 


4 
u 


2 


1 



SIXTEEN BITS 



Figure 1.3 

Direct conversion between decimal and binary is seldom needed. Such 
conversions usually pass through an intermediate number system, called 
hexadecimal. 

Hexadecimal Notation 

Binary is an excellent system for the computer, but it is inconvenient for 
most programmers. If one programmer asks another, "What address should 



6 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



I use for some activity?", an answer sucli as "Address 
^□□DIDDIDIOIOIIDD" might be correct but would probably be un- 
satisfactory. There are too many digits. 

Hexadecimal is a code used by humans to conveniently represent binary 
numbers. The computer uses binary, not hexadecimal; programmers use 
hexadecimal because binary is cumbersome. 

To represent a binary number in hexadecimal, the bits must be grouped 
together four at a time. If we take the binary value given above and split 
it into groups of four, we get 

□ ODl HDD 

Now each group of four bits is represented by a digit as shown in the 
following table: 

DDDO-Q nma-A inao-a iidq-c 

□□01-1 OlDl-S l^Dl-R llDl-D 
DllQ-t l^lQ-a lllQ-E 
□011-3 □111-? IDll-B 1111-F 

Thus, the number would be represented as hexadecimal 12 AC. A dollar 
sign is often prefixed to a hexadecimal number so that it may be clearly 
recognized:$lEAC. 

The same type of weighting is applied to each bit of the group of four as 
was described before. In other words, the rightmost bit (bit zero) has a 
weight of 1 , the next left a weight of 2, the next a weight of 4, and the 
leftmost bit (bit three) a weight of 8. If the total of the weighted bits exceeds 
nine, an alphabetic letter is used as a digit: A represents ten; B, eleven; 
C, twelve; and F, fifteen. 

Eight-bit numbers are represented with two hexadecimal digits. Thus, 
^OlQllOll may be written as $53. 

Hexadecimal to Decimal 

As we have seen, hexadecimal and binary numbers are easily inter- 
changeable. Although we will usually write values in "hex," occasionally 
we will need to examine them in their true binary state to see a particular 
information bit. 

Hexadecimal isn't hard to translate into decimal. You may recall that in 
early arithmetic we were taught that the number 24 meant, "two tens and 
four units." Similarly, hexadecimal 24 means "two sixteens and four units," 
or a decimal value of 36. By the way, it's better to say hex numbers as 



FIRST CONCEPTS 



"two four" rather than "twenty-four," to avoid confusion with decimal val- 
ues. 

The formal procedure, or algorithm, to go from hex to decimal Is as follows. 

Step 1 : Take the leftmost digit; if it's a letter A to F , convert It to the appropriate 
numeric value (A equals 10, B equals 11, and so on). 

Step 2: If there are no more digits, you're finished; you have the number. Stop. 

Step 3: Multiply the value so far by sixteen. Add the next digit to the result, 
converting letters if needed. Go back to step 2. 

Using the above steps, let's convert the hexadecimal number $15ac. 
Step 1: The leftmost digit is 1. 
Step 2: There are more digits, so we'll continue. 
Step 3. 1 times lb is It, plus E gives Ifl. 
Step 2: More digits to come. 

Step 3: la times lb is Eflfl, plus ID (for A) gives E^fl. 
Step 2: More digits to come. 

Step 3: Eqa X lb is -^Tbfl, plus IS (forC)gives <7fl0. 
Step 2: No more digits: ^7flD is the decimal value. 

This is easy to do by hand or with a calculator. 

Decimal to Hexadecimal 

The most straightfonward method to convert from decimal to hexadecimal 
is to divide repeatedly by 16; after each division, the remainder is the next 
hexadecimal digit, working from right to left. This method is not too well 
suited to small calculators, which usually don't give remainders. The fol- 
lowing fraction table may offer some help: 

. .ESDD-A .50DD-fl .750D-C 

.□bE5-l .31E5-5 .5t25-q .fll25-D 

.155D-E .375D-fc .t55D-ft .fl75D-E 

.lfl75-3 .-^375-7 .tfi75-B .q375-F 

If we were to translate 4780 using this method, we would divide by 16, 
giving 298.75. The fraction tells us the last digit is C; we now divide 298 
by 16, giving 18.625. The fraction corresponds to A, making the last two 
digits AC. Next we divide 18 by 16, getting 1.125— now the last three 
digits are 2 AC. We don't need to divide the one by 16, although that would 
work; we just put it on the front of the number to get an answer of $ 1 E AC. 



There are other methods of performing decimal-to-hexadecimal conver- 



8 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



sions. You may wish to look them up in a book on number systems. 
Altematively, you may wish to buy a calculator that does the job electron- 
ically. Some programmers get so experienced that they can do conver- 
sions in their heads; I call them "hex nuts." 

Do not get fixed on the idea of numbers. Memory locations can always 
be described as binary numbers, and thus may be converted to decimal 
or hexadecimal at will. But they may not mean anything numeric: the 
memory location may contain an ASCII coded character, an instruction, 
or any of several other things. 

Memory Elements 

There are generally three types of devices attached to the memory busses 
(address, data, and control busses): 

• RAM: Random access memory. This is the read and write memory, where 
we will store the programs we write, along with values used by the program. 
We may store information into RAM, and may recall the information at any 
time. 

• ROM: Read only memory. This is where the fixed routines are kept within the 
computer. We may not store information into ROM; its contents were fixed 



ADDRESS BUS 



650x 



MEMORY BUS 



RAM 
(READ 

AND 
WRITE) 



ROM 
(READ 
ONLY) 



lA 

(SPECIAU 



CONNECTIONS 
TO "OUTSIDE WORLD' 



Figure 1.4 



FIRST CONCEPTS 



9 



when the ROM was made. We will use program units (subroutines) stored in 
ROM to do special tasks for us, such as input and output. 

• I A: Interface adaptor chips. These are not memory in the usual sense; but, 
these chips are assigned addresses on the address bus, so we call them 
"memory-mapped" devices, information may be passed to and from these 
devices, but the information is generally not stored in the conventional sense. 
I a chips contain such functions as: input/output (I/O) Interfaces that serve 
as connections to the "outside world"; timing devices; Interrupt control sys- 
tems; and sometimes specialized functions, such as video control or sound 
generation. I ft chips come in a wide variety of designs, Including the PI ft 
(peripheral Interface adaptor), the VIA (versatile Interface adaptor), the Clft 
(complex Interface adaptor), the VIC (video interface chip), and the SID 
(sound Interface device). 

Within a given computer, some addresses may not be used at all. Some 
devices may respond to more tlian one address, so tliat tfiey seem to be 
in two places in memory. 

An address may be tliought of as split in two parts. One part, usually the 
high part of the address, selects the specific chip. The other part of the 
address selects a particular part of memory within the chip. For example, 
in the Commodore 64, the hex address $DD2D (decimal 53EflD) sets 
the border color of the video screen. The first part of the address (roughly, 
$DD . . .) selects the video chip; the last part of the address (. . . ED) 
selects the part of the chip that controls border color. 

Microprocessor Registers 

Within the 650x chip are several storage areas called registers. Even 
though they hold information, they are not considered "memory" since 
they don't have an address. Six of the registers are important to us. Briefly, 
they are: 

PC: (16 bits) The program counter tells where the next 

instruction will come from. 
A, X and Y (8 bits each) These registers hold data. 

SR The status register, sometimes called PSW 

(processor status word), tells about the re- 
sults of recent tests, data handling, and so 
on. 

S P The stack pointer keeps track of a temporary 

storage area. 

We will talk about each of these registers in more detail later. At the 
moment, we will concentrate on the PC (program counter). 



10 MACHINE LANGUAGE FOR COMMODORE MACHINES 




ADDRESS BUS 



DATA BUS 



650x CHIP 



Figure 1.5 

Instruction Execution 

Suppose that the 650x is stopped (not an easy trick), and that there is a 
certain address, say $1534 , in the PC. The moment we start the micro- 
computer, that address will be put out to the address bus as a read address, 
and the processor will add one to the value in the PC. 

Thus, the contents of address $123 A will be called for, and the PC will 
change to $1535. Whatever information comes in on the data bus will 
be taken to be an instruction. 

The microprocessor now has the instruction, which tells it to do something. 
The action is performed, and the whole action now repeats for the next 



PC 






$1234 1 














ADDRESS 




BUS 



PC 




1 $1235 


$1234 
INSTRUCTION ^ 




ADDRESS 
BUS 




DATA BUS 



Figure 1.6 



FIRST CONCEPTS 



11 



instruction. In other words, address $1235 will be sent to memory, and 
the PC will be incremented to $153 1. 

You can see that the processor works in the same way that most computer 
languages do: an instruction is executed, and then the computer proceeds 
to the next instruction, and then the next, and so on. We can change the 
sequence of execution by means of a "jump" or "branch" to a new location, 
but normally, it's one instruction after another. 

Data Registers: A, X, and Y 

Any of three registers can be used to hold and manipulate eight bits of 
data. We may load information from memory into A, X, or Y; and we may 
store information into memory from any of A, X, or Y. 

Both "load" and "store" are copying actions. If I load A (LDA) from 
address $E3<5, I make a copy of the contents of hex E3<5 into A; but 
E3AS still contains its previous value. Similarly, if I store Y into $3^ St., 
I make a copy of the contents of Y into that address; Y does not change. 

The 650x has no way of moving information directly from one memory 
address to another. Thus, this information must pass via A, X, or Y; we 
load it from the old address, and store it to the new address. 

Later, the three registers will take on individual identities. For example, 
the A register is sometimes called the accumulator, since we perform 
addition and subtraction there. For the moment, they are interchangeable: 
we may load to any of the three, and we may store from any of them. 

First Program Project 

C128 note: The programming task that follows will need to be slightly 
changed if you are using a Commodore 128 in C128 mode. In particular, 
the program will need to be written into a different part of memory from 
that which Is shown below. Check Appendix E, Exercises for the Com- 
modore C128, page 251 for the correct CI 28 coding. ^ n r, o 

Here's a programming task: locations $0330 and $D3fll contain in- 
formation. We wish to write a program to exchange the contents of the 
two locations. How can we do this? 

We must make up a plan. We know that we cannot transfer information 
directly from memory to memory. We must load to a register, and then 
store. But there's more. We must not store and destroy data in memory 
until that data has been safely put away. How can we do this? 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Here's our plan. We may load one value into A (say, the contents of 
$ 3 a 0), and load the other value into X (the contents of $ □ 3 fl 1). Then 
we could store a and X back, the other way around. 

We could have chosen a different pair of registers for our plan, of course: 
A and Y, or X and Y. But let's stay with the original plan. We can code 
our plan in a more formal way: 

LDA $0360 (bring in first value) 
LDX $0351 (bring in second value) 
STft $03fll (store in opposite place) 
STX $D3flD (and again) 

You will notice that we have coded "load A" as LDA, "load X" as 
LDX, "store A" asSTA,and "store X" as STX. Every command 
has a standard three-letter abbreviation called a mnemonic. Had we used 
the Y register, we might have needed to use LDY and STY. 

One more command is needed. We must tell the computer to stop when 
it has finished the four instructions. In fact, we can't stop the computer; 
but if we use the command BRK (break), the computer will go to the 
machine language monitor (MLM) and wait for further instructions. We'll 
talk about the MLM in a few moments. 

We have written our program in a notation styled for human readability, 
called assembly language. But the computer doesn't understand this no- 
tation. We must translate it to machine language. 

The binary code for LDA is ^IDlOllDl, or hexadecimal AD. That's 
what the computer recognizes; that's the instruction we must place in 
memory. So we code the first line: 

AD flO 03 LDA $D3flO 

It's traditional to write the machine code on the left, and the source code 
on the right. Let's look closely at what has happened. 

LDA has been translated into $AD. This is the operation code, or op 
code, which says what to do. It will occupy one byte of memory. But we 
need to follow the instruction with the address from which we want the 
load to take place. That's address $D3flD; it's sixteen bits long, and so 
it will take two bytes to hold the address. We place the address of the 
instruction, called the operand, in memory immediately behind the instruc- 
tion. But there's a twist. The last byte comes first, so that address $ □ 3 a □ 
is stored as two bytes: fiO first and then D3. 



FIRST CONCEPTS 



13 



1 



This method of storing addresses — low byte first — is standard in the 650x. 
It seems unusual, but it's there for a good reason. That is, the computer 
gets extra speed from this "backwards" address. Get used to It; you'll see 
it again, many times. 

Here are some machine language op codes for the instructions we may 
use. You do not need to memorize them. 

LDfl-aD LDX-fiE LDY-aC BRK-DD 

STA-flD STX-flE STY-aC 

Now we can complete the translation of our program. 



AD 


ao 


03 


LDA 


$D3aD 


A£ 


ai 


03 


LDX 


$D3fll 


flD 


ai 


03 


STA 


$D3ai 


as 


an 


03 


STX 


$03aD 


□ □ 






BRK 





On the right, we have our plan. On the left, we have the actual program 
that will be stored in the computer. We may call the right side assembly 
code and the left side machine code, to distinguish between them. Some 
users call the right-hand information source code, since that's where we 
start to plan the program, and the left-hand program object code, since 
that's the object of the exercise— to get code into the computer. The job 
of translating from source code to object code is called assembly. We 
performed this translation by looking up the op codes and translating by 
hand; this is called hand assembly. 

The code must be placed into the computer. It will consist of 13 bytes: 

AD ao 03 AE ai 03 ao ai d3 aE ao 03 oo. That's the 
whole program. But we have a new question: where do we put It? 



Choosing a Location 

We must find a suitable location for our program. It must be placed into 
RAM memory, of course, but where? 

For the moment, we'll place our program into the ^ssette buffer , starting 
at address $D33C (decimal a 2 a). That's a goodplace to puTshort test 
programs, which is what we will be writing for a while. 

^ $0600 dz^jmxl ^814 

Now that we've made that decision, we face a new hurdle: how do we get 
the program in there? To do that, we need to use a machine language 
monitor. 



14 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Monitors: What They Are 

All computers have a built-in set of programs called an operating system 
that gives the machine its style and basic capabilities. The operating sys- 
tem tal<es care of communications — reading the l<eyboard, mal<ing the 
proper things appear on the screen, and transferring data between the 
computer and other devices, such as disk, tape, or printer. 

When we type on the computer keyboard, we use the operating system, 
which detects the characters we type. But there's an extra set of programs 
built into the computer that must decide what we mean. When we are 
using the BASIC language, we'll be communicating with the BASIC mon- 
itor, which understands BASIC commands such as NEW, LOAD, LIST, 
or BUN. It contains editing features that allow us to change the BASIC 
program that we are writing. 

But when we switch to another system — often another language — we'll 
need to use a different monitor. Commands such as NEW or LIST don't 
have any meaning for a machine language program. We must leave the 
BASIC monitor and enter a new environment: the machine language mon- 
itor. We'll need to learn some new commands because we will be com- 
municating with the computer in a different way. 



The Machine Language Monitor 

Most PET/CBM computers have a simple MLM (machine language mon- 
itor) built in. It may be extended with extra commands. The Commodore 
PLUS/4 contains a very powerful MLM. The VIC-20 and Commodore 64 
do not have a built-in MLM, but one can be added. Such a monitor may 
be either loaded into RAM or plugged in as a cartridge. Monitors may be 
purchased or obtained from User clubs. 

Most machine language monitors work in a similar way, and have about 
the same commands. To proceed, you'll need an MLM in your computer. 
Use the built-in one, plug it in, load it in, or load and run . . . whatever the 
instructions tell you. On a PET/CBM machine, typing the command SYS 
A will usually switch you to the built-in monitor. After an MLM has been 
added to a VIC or Commodore 64, the command SYS fl will usually get 
you there. On the Commodore PLUS/4, the BASIC command MONITOR 
will bring the monitor into play. 



FIRST CONCEPTS 



15 



C128 note: When the Commodore 128 is in C64 mode, it needs to have 
a monitor program loaded, as does the Commodore 64. When in the C128 
mode, however, the command MONITOR wili bring the monitor into piay 
There wili be slight differences in the screen display of this monitor. Ap 
pendix H contains information on the various monitor commands and 
formats. 

Caution: Occasionally, you may run across a monitor which uses— and 
changes — memory locations in the address range $D33C to $D3FD, 
which is where we will put many of our programs. There is a version of 
program MICROMON which does this. Such a monitor will create problems 
for us as we try to work the following examples, since our programs and 
data will be changed by the monitor as we use it. The built-in monitors 
will certainly not have any problem. If you encounter any problems with 
the following examples, and it appears that your program is being mys- 
teriously changed, switch to another machine language monitor. 



Monitor Display 

The moment you enter the ML M, you'll see a display that looks somethino 
like this: 

B* 

PC SR ftC XR YR SP 
□ □□5 50 SA 23 tfi Ffl 

The cursor will be flashing to the right of the period on the bottom line. 
The exact appearance of the screen information may vary according to 
the particular monitor you are using. Other material may be displayed— 
in particular, a value called IRQ— which we will ignore for the time being. 

The information you see may be interpreted as follows: 
B*— we have reached the MLM by means of a "break." More about that later. 
PC— The value shown below this title is the contents of the program counter. 
This indicates where the program "stopped." In other words, if the value shown 
is address DUOS, the program stopped at address DDD^, since the PC is 
ready to continue at the following address. The exact value (ODD A versus 
□ □□5) may vary depending on the particular MLM. 

S R— The value shown below shows the status register, which tells us the results 
of recent tests and data operations. We'd need to split apart the eight bits and 
look at them individually to establish all the information here; we will do this at 
a later time. 



76 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



ftC, XR, and YR— The values shown below these three titles are the contents 
of our three data registers: R, X, and Y. 

SP— The value shown below is that of the stack pointer, which Indicates a 
temporary storage area that the program might use. A value of F fl , for example, 
tells us that the next item to be dropped into the stack area would go to address 
$□ IF fl in memory. More on this later. 

You will notice that the display printed by the monitor (called the register 
display) shows the internal registers within the 650x chip. Sometimes there 
is another item of information, titled IRQ, in this display. It doesn't belong, 
since it does not represent a microprocessor register. IRQ tells us to what 
address the computer will go if an interrupt occurs; this information is 
stored in memory, not within the 650x. 



M L M Commands 

The machine language monitor is now waiting for you to enter a command. 
The old BASIC commands don't work any more; LIST or NEW or SYS 
are not known to the MLM. We'll list some popular commands in a moment. 
First, let's discuss the command that takes us back to BASIC. 

X exits the MLM and returns to the BASIC monitor. Try it. Remember 
to press RETURN after you've typed the X, of course. You will return to 
the BASIC system, and the BASIC monitor will type READY. You're back 
in familiar territory. Now go back to the monitor with SYS^orSYSflor 
MONITOR as the case may be. BASIC ignores spaces: it doesn't matter 
if you type SYSflorSYS fl; just use the right number for your machine 
(A for PET/CBM, fl for VIC/64). 

Remember: BASIC commands are no good in the MLM, and machine 
language monitor commands (such as X) are no good in BASIC. At first, 
you'll give the wrong commands at the wrong time because it's hard to 
keep track of which monitor system is active. If you type in an MLM 
command when you're in BASIC, you'll probably get a ? SYNTAX ERROR 
reply. If you type in a BASIC command when you're in the machine lan- 
guage monitor, you'll probably get a question mark in the line you typed. 

Some other MLM commarids are as follows: 

M IDID (display memory from hex 1 □ □ □ to 

!□!□) 

R (display registers . . . again!) 



FIRST CONCEPTS 



17 



G □ 3 3 C (go to D 3 3 C and start running a 

program) 

Do not enter this last (G) command. There is no program at address 
$03 3C yet, so the computer would execute random instructions and we 
would lose control. 

There are two other fundamental instructions that we won't use yet: they 
are S for save and L for load. These are tricky. Until you learn about 
BASIC pointers (Chapter 6), leave them alone. 

Displaying Memory Contents 

You'll notice that there is a command for displaying the contents of mem- 
ory, but there doesn't seem to be one for changing memory. You can do 
both, of course. 

Suppose we ask to display memory from $lDDOto$lDlD with the 
command 

Be careful that you have exactly one space before each address. You 
might get a display that looks something like this: 

.:1DDD 11 3A E< OD 51 3E DA kk 
.rlDDfl 50 Ak <q AJ) ED A2 55 5A 
.:1D1D SA AS 52 Ah A^ AS AC AA 

C128 note: The above display will differ slightly if you are using C128. 
The section Exercises for the Commodore 128, in Appendix E, gives 
details. 

The four-digit number at the start of each line represents the address in 
memory being displayed. The two-digit numbers to the right represent the 
contents of memory. Keep in mind that all numbers used by the machine 
language monitor are hexadecimal. 

In the example above, $ 1 □ □ □ contains a value of$ll;$iaai contains 
a value of $3 A; and so on, until $1DD7, which contains a value of $kk. 
We continue with address $!□□ & on the next line. Most monitors show 
eight memory locations on each line, although some VIC-20 monitors show 
only five because of the narrow screen. 

We asked for memory locations up to address $ 1 D 1 D only; but we get 
the contents of locations up to $1D17 in this case. The monitor always 
fills out a line, even if you don't ask for the extra values. 



18 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Changing Memory Contents 

Once we have displayed the contents of part of memory, we can change 
that part of memory easily. All we need to do is to move the cursor until 
it is positioned over the memory contents in question, type over the value 
displayed, and then press BETUBN. 

This is quite similar to the way BASIC programs may be changed; you 
may type over on the screen, and when you press BET URN, the new line 
replaces the old. The general technique is called screen editing. 

If you have displayed the contents of memory, as in the example above, 
you might like to change a number of locations to zero. Don't forget to 
strike BETUBN so that the change on the screen will take effect in mem- 
ory. Give another M memory display command to confirm that memory 
has indeed been changed. 



Changing Registers 

We may also change the contents of registers by typing over and pressing 
BETUBN. You may take a register display with command B, and then 
change the contents of PC, AC, XR, and YB. Leave the contents of SB 
and SP unchanged — tricky things could happen unexpectedly if you ex- 
periment with these two. 



Entering the Program 



C128 note: Remember to check Exercises for the Commodore 128, in 
Appendix E, for the appropriate code. 

We might rewrite our program one last time, marking in the addresses 
that each instruction will occupy. You will recall that we have decided to 
put our program into memory starting at address $0B3C (part of the 
cassette buffer). 

□33C AD 50 03 LDR $D3flO 

□33F AE fll 03 LDX $D3fll 

Q3AE flD fll 03 STA $D3fll 

□3<5 flE flD 03 STX $D3flD 

U3A& UU 



FIRST CONCEPTS 



79 



Remember that most of the above listing is cosmetic. The business end 
of the program is the set of two-digit hex numbers shown to the left. At 
the extreme left, we have addresses— that's information, but not the pro- 
gram. At the right, we have the "source code"— our notes on what the 
program means. 

How do we put it in? Easy. We must change memory. So, we go to the 
MLM, and display memory with 

M 0330 03A5 

We might have anything in that part of memory, but we'll get a display 
that looks something like 

.:D33C XX XX xx xx xx xx xx xx 
.:D3AA XX XX XX xx xx xx xx xx 

You won't see "xx," of course; there will be some hexadecimal value 
printed for each location. Let's move the cursor back and change this 
display so that it looks like this: 

•:D33C AD flD D3 AE fll 03 flD fll 
.:Q3AA Q3 flE flD 03 □□ xx xx xx 

Don't type in the "xx"— just leave whatever was there before. And be 
sure to press RETURN to activate each line; if you move the cursor down 
to get to the next line without pressing RETURN, the memory change 
would not happen. 

Display memory again (M 0330 034 fl) and make sure that the 
program is in place correctly. Check the memory display against the pro- 
gram listing, and be sure you understand how the program is being tran- 
scribed into memory. 

If everything looks in order, you're ready to run your first machine language 
program. 

Preparation 

There's one more thing that we need to do. If we want to swap the contents 
of addresses $03flD and $0361, we'd better put something into those 
two locations so that we'll know that the swap has taken place correctly. 

Display memory with M □3flD □3fll and set the resulting display 
so that the values are 

.:D3flO 11 XX XX xx xx xx xx 



20 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Remember to press RETURN. Now we may run our program; we start it 
up with 

G 033C 

The program runs so quicl<ly that it seems instantaneous (the run time is 
less than one fifty thousandth of a second). The last instruction in our 
program was BRK for break, and that sends us straight to the MLM with 
a display of *B (for breal<, of course) plus all the registers. 

Nothing seems to have changed. But wait. Look carefully at the register 
display. Can you explain the values you see in the AC and XR registers? 
Can you explain the PC value? 

Now you may display the data values we planned to exchange. Give the 
memory display command M 0330 □361— have the contents of 
the two locations changed? 

They'd better have changed. Because that's what the writing of our pro- 
gram was all about. 

Things You Have Learned 

— Computers use binary. If we want to work with the inner fabric of the computer, 
we must come to terms with binary values. 

—Hexadecimal notation is for humans, not for computers. It's a less clumsy 

way for people to cope with binary numbers. 
—The 650x microprocessor chip communicates with memory by sending an 

address over its memory bus. 

— The 650x has internal work areas called registers. 

— The program counter tells us the address from which the processor will get 
its next instruction. 

—Three registers, called A, X, and Y, are used to hold and manipulate data. 
They may be loaded from memory, and stored Into memory. 

—Addresses used in 650x Instructions are "flipped:" the low byte comes first, 
followed by the high byte. 

— The machine language monitor gives us a new type of communications path 
into the computer. Among other things, it allows us to inspect and change 
memory in hexadecimal. 

Detail: Program Execution 

When we say G 033C to start up our program, the microprocessor goes 
through the following steps: 



FIRST CONCEPTS 



21 



1. It asks for the contents of $033C; it receives SAD, which it recognizes as 
the op code " load ft , " It realizes that it will need a two-byte address to 
go with this instruction. 

2. It asks for the contents of $03 3D, and then $033E. As it receives the 
values of $ao and $03 it gathers them into an "instruction address." 

3. The microprocessor now has the whole instruction. The PC has moved along 
to $ 3 3 F . The 650x now executes the instruction. It sends address $0360 
to the address bus; when it gets the contents (perhaps $11), it delivers this 
to the R register. The A register now contains $11. 

4. The 650x is ready to take on the next instruction; the address $033F goes 
from the PC out to the address bus; and the program continues. 

Questions and Projects 

Do you know that your computer has a part of memory called "screen 
memory"? Whatever you put Into that part of memory appears on the 
screen. You'll find this described in BASIC texts as "screen POKE-ing." 

The screen on the PET/CBM is at SflDDD and up; on the VIC, it's often 
(but not always) at $1EDD and up; on the Commodore 64, it's usually at 
$ □ ; and on the PLUS/4, it may be found at $ □ C □ □ . With the C1 28, 
the 40-column screen is at $ □ □, but If you are in the 80-column mode, 
the screen is not mapped directly to memory. 

If you write a program to store information in the screen memory address, 
the appropriate characters will appear on the screen. You might like to try 
this. You can even "swap" characters around on the screen, if you wish. 

Two pitfalls may arise. First, you might write a perfect program that places 
information near the top of the screen; then, when the program finishes, 
the screen might scroll, and the results would disappear. Second, the VIC 
and Commodore 64 use color, and you might inadvertently produce white- 
on-white characters; these are hard to see. 

Here's another question. Suppose I asked you to write a program to move 
the contents of five locations, $D3fiD to $D3fl^, in an "end-around" 
fashion, so that the contents of $0360 moved to$D3fll, $D3fllto 
$D3fl2, and so on, with the contents of $Q3&A moved to $03fiD. At 
first glance, we seem to have a problem: we don't have five data registers, 
we have only three (A, X, and Y). Can you think of a way of doing the 
job? 



This chapter discusses: 

• Calling machine language subroutines 

• Trite PRINT subroutine 

• immediate addressing 

• Calling machine language from BASIC 

• Tiny assembler programs 

• Indexed addressing 

• Simple loops 

• Disassembly 



24 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Calling Machine Language Subroutines 

In BASIC, a "package" of program statements called a subroutine may 
be brought into action with a GOSUB command. The subroutine ends with 
a RETURN statement, which causes the program to return to the calling 
point, i.e., the statement immediately following GOSUB. 

The same mechanism is available in machine language. A group of in- 
structions may be invoked with a juntp subroutine (JSR) command. The 
650x goes to the specified address and performs the instructions given 
there until it encounters a return from subroutine (RTS) command, at 
which time it resumes execution of instructions at the calling point: the 
instruction immediately following JSR. 

For example, if at address $D33C I code the instruction JSR $153^, 
the 650x will change its PC to $1234 and start to take instructions from 
that address. Execution will continue until the instruction RTS is encoun- 
tered. At this time, the microprocessor would switch back to the instruction 
following the JSR, which in this case would be address $D33F (the JSR 
instruction is three bytes long). 

As in BASIC, subroutines may be "nested;" that is, one subroutine may 
call another, and that subroutine may call yet another. We will deal with 
subroutine mechanisms in more detail later. For the moment, we'll concern 
ourselves with calling prewritten subroutines. 

Prewritten Subroutines 

A number of useful subroutines are permanently stored in the ROM mem- 
ory of the computer. All Commodore machines have a standard set of 
subroutines that may be called up by your programs. They are always at the 
same addresses, and perform in about the same way regardless of which 
Commodore machine is used: PET, CBM, Commodore 64, PHJS/4, Com- 
modore 128, or VIC-20. These routines are called the kernel subroutines. 
Details on them can be found in the appropriate Commodore reference 
manuals, but we'll give usage information here. 

The original meaning of the term kernel seems to be lost in legend. It was 
originally an acronym, standing for something like "Keyboard Entry Read, 
Network and Link." Today, it's just the label we apply to the operating 
system that makes screen, keyboard, other input/output and control mech- 
anisms work together. To describe this central control system, we might 
choose to correct the spelling so as to get the English word, "kernel." For 
now, we'll use Commodore's word. 



CONTROLLING OUTPUT 



25 



The three major kernal subroutines that we will deal with in the next few 
chapters are shown here: 

Address Name What it does 

$FFDE CHEOOT Outputs an ASCII character 

$FFE< GETIN Gets an ASCII character 

$FFE1 STOP Checks the RUN/STOP key 

With the first two subroutines, we can input and output data easily. The 
third allows us to honor the RON/STOP key, to guard against certain types 
of programming error. In this chapter, we'll use CH ROOT to print infor- 
mation to the screen. 

C H R U T— The Output Subroutine 

The CHROUT subroutine at address $FFDE may be used for all types 
of output: to screen, to disk, to cassette tape, or to other devices. It's 
similar to PRINT and PRINT#, except that it sends only one character. 
For the moment, we'll use CHROUT only for sending information to the 
computer screen. 



Subroutine: CHROUT 
Address: $FFDE 

Action: Sends a copy of the character in the A register to the 

output channel. The output channel is the computer screen 
unless arrangements have been made to switch it. 

The character sent is usually ASCII (or PET ASCII). When sent to the 
screen, all special characters — graphics, color codes, cursor move- 
ments—will be honored in the usual way. 

Registers: All data registers are preserved during a CHROUT call. 
Upon return from the subroutine, A, X, and Y will not have changed. 

Status: Status flags may be changed. In the most recent Commodore 
machines, the C (carry) flag indicates some type of problem with output. 



To print a letter X on the screen, we would need to follow these steps: 

1. Bring the ASCII letter X ($5fl) into the A register; 

2. JSR to address $FFDE. 



26 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Why Not POKE? 



It may seem that there's an easier way to make things appear on the 
screen. We might POKE information directly to screen memory; in ma- 
chine language, we would call this a store rather than a POKE, of course. 
The moment we change something in this memory area, the information 
displayed on the screen will change. Screen memory is generally located 
at the following addresses: 

PET/CBM: $&□□□ and up (decimal BB7tfi) 

Commodore 64 and 1 28: $ □ < □ □ and up (decimal IDEA) 

264/364 $□€□□ and up (decimal 307 B) 

VIC-20: $1EDD and up (decimal 7 tflD) 

The screen memory of the VIC-20 in particular may move around a good 
deal, depending on how much additional RftM memory has been fitted. 

Occasionally, screen POKEs are the best way to do the job. But most of 
the time we'll use the CHROOT, $FFDE subroutine. Here are some of 
the reasons why: 

• As with PRINT, we won't need to worry about where to place the next 
character; it will be positioned automatically at the cursor point. 

• If the screen is filled, scrolling will take place automatically. 

• Screen memory needs special characters. For example, the character X has 
a standard ASCII code of $5a, but to POKE it to the screen we'd need to 
use the code $lfl. The CHROOT subroutine uses $53. 

• Screen memory may move around, depending on the system and the pro- 
gram. The POKE address would need to change; but CHROUT keeps 
working. 

• Special control characters are honored: $DD for RETURN, to start a new 
line; cursor movements; color changes. We can even clear the screen by 
loading the screen-clear character ($R3) and calling $FFDB. 

• To POKE the screen of the Commodore machines with color, the corre- 
sponding color nibble memory must also be POKEd (see the appropriate 
memory map in Appendex C). With the subroutine at $FFDE, color is set 
automatically. 



A Print Project 

Let's write some code to print the letter H on the screen. Once again, we'll 
use address $ 0330, the cassette buffer, to hold our program. Reminder: 
be sure to have your monitor loaded and ready before you start this project. 



CONTROLLING OUTPUT 



27 



First, the plan; we lay out the instructions 

LDa #$4fl 

We're using a new symbol (#) to signal a special type of information. It 
goes by a variety of names: pounds sign, sharp, hash mark, or numbers 
sign. A more formal name for the symbol is octothorpe, meaning "eight 
points." Whatever you call it, the symbol means "the following information 
is not an address, it's a value." In other words, we don't want the computer 
to go to address $<fl, we want it to load the A register with the value 
$^ a, which represents the ASCII letter H. This type of information access 
is called immediate addressing. In other words, take the information im- 
mediately, don't go to memory for it. 

JSR $FFDE 

The previous instruction brought the letter H into the A register; this one 
prints it to the screen. Now all we need to do is quit. BEK takes us to the 
machine language monitor. 

Monitor Extensions 

We could repeat the steps of the previous chapter: hand-assembling the 
source code into machine language, and then placing it into memory. We 
would need to know the instruction codes, and then do a careful translation. 
But there's an easier way. 

Most machine language monitors contain extra commands to help us do 
this type of mechanical translation. We'll use the assembler feature of 
these monitors. 

Most monitors contain the assemble (A) command. The notable excep- 
tion is the built-in monitors within the PET/CBM; these, however, can be 
extended by loading in a "monitor extension" program such as Supermen. 
The Commodore PLUS/4 series contains an extended monitor, which 
includes the A command. 

These assemblers are often called nonsymbolic assemblers. This means 
that whenever an address is needed, you must furnish that exact address. 
You cannot type in a name such as CHROUT and expect the tiny assem- 
bler to know what address that represents; instead, you must type $ FFD 5. 

C128 note: Remember to check Exercises for the Commodore 128, in 
Appendix E, for the appropriate coding, and information on how the CI 28 
assembler works. 



28 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Load your monitor or monitor extension. Do any setup that may be needed. 
Tlien type tfie foliowing monitor command: 

ft 0330 LDft #$<fl 

We are asking tlie computer to assemble (ft) at address $D33C (note 
we don't use tlie $ here) the command LDft, Load ft, the immediate value 
of $<a, which represents the ASCII letter H. When you press RETURN 
after entering this line, the computer may do either of two things: 

1 . It may do nothing except print a question mark somewhere on the line. The 
question mark Indicates an error in your coding. If the question mark appears 
directly after the letter ft, your monitor does not understand the ft assemble 
Instruction; get another monitor or properly set up the one you have. 

2. Or, it will correctly translate your instruction, and put the object code Into 
memory starting at the address specified. In this case, that would happen 
to be $AR at address $DB3C and $^fi at address $0330. It would then 
help you by printing part of the next expected instruction. The computer 
expects that you will type a line starting with 

A naaE 

It places the first part of this line on the screen to save you typing. The 
screen should now look like this: 

A 0330 LDft #$A& 
ft □33E 

You may now complete the instruction by typing in JSR $FFDE and 
pressing RETURN. Again, the computer will anticipate your next line by 
printing ft 0341, which allows you to type in the final command, BRK. 
The screen now looks like this: 

ft 033C LDft #$4fl 
ft □33E JSR $FFD5 
ft □3^1 BRK 
ft □3/;2 

The computer is still waiting for another instruction. We have no more 
instructions, so we press RETURN to signal that we're finished. 

At this point, our program is stored in memory. The instructions have been 
assembled directly into place, and the object code is hopefully ready to 
go. 

Note that this saves us the trouble of remembering— or looking up— the 
op codes for each instruction. And we don't need to keep track of how 
long each instruction should be; the assembler does it for us. 



CONTROLLING OUTPUT 



29 



If you like, you can display memory and look at the object program with 
theM 0330 □3^1. You'll see the bytes of your program in memory: 

. :D33C ftq 4fl 50 D5 FF □□ xx xx 

The first six bytes are your program. The last two bytes don't matter: they 
were whatever was in that part of memory before. We don't care what is 
there, since the program will stop when it reaches the BBK ($□□) at 
address $ □ 3 < 1 ; it won't be concerned with the contents of memory at 
$D34E or $03^3. 

Checking: The Disassembler 

When we changed our source code into object code, we called this process 
of translation assembly, and we called a program that did the job an 
assembler. 

Now we've written a program and it's safely stored in memory. We have 
inspected memory and have seen the bytes there; but they are hard to 
read. It would be convenient if we could perform an inverse assembly, 
that is, take the contents of memory and translate it into source code. The 
monitor has this capability, called a disassembler. 

If we ask the computer to disassemble the code starting at $D33C, it will 
examine the code there and establish that the contents ($ AR) correspond 
to an LDR immediate command. It will then print for our information LDA 
#$4 fl, which is much more readable than the original two bytes, ftR A&. 

Give the command D 033C and press RETURN. D stands for disas- 
semble, of course, and the address must follow. 

The computer will now show a full screen of code. On the left is the address 
followed by the bytes making up the instruction. On the right is the re- 
constructed source code. The screen shows much more memory than our 
program needs. Again, we ignore all lines beyond address $Q3A1, which 
is the last instruction of our program. Anything following is "junk" left in 
memory that the program does not use. 

An interesting feature of most disassembly listings is that the cursor is left 
flashing on the last line of the disassembly rather than on the line below. 
When you have a large program, this allows you to type the letter D 
followed by RETURN and the next part of your program will immediately 
be displayed. On the other hand, if you don't want to disassemble more 
code, press the cursor down key and move to a "clean" line before typing 
your next instruction. 



30 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



A disassembly is a good way to check for errors. If you find an error in 
tiie listing, you may correct that line by re-assembling it, using the ft 
command once again. Minor errors may be corrected directly on the left- 
hand side of the disassembly listing. In other words, suppose that you had 
incorrectly coded LDft #$5fl during the assembly phase; when you per- 
form the disassembly, this line will show as 

. / Q33C ftq 5fl LDfi #$5a 

You recognize that the 56 should be A&; you may move the cursor up— 
use cursor home if you wish — and type over the value on the left-hand 
side. In this case, you place the cursor over the 5, type A to change the 
display to < fl, and press RETURN. You will see from the display that the 
problem has been fixed. 



If necessary, move the cursor down to an empty line. Type the command 
G 03 3 C and the program will run. Again, it doesn't take long; the break 
back to the MLM seems instantaneous. Where's the letter H that we were 
supposed to print? It's hard to see, but it's there. Look at your G 0330 
command and you'll see it. 

Project for enthusiasts: Can you add to the program and print HI? The 
ASCII code for the letter I is $A'=\. Can you add again and print HI on 
a separate line? The ASCII code for a RETURN is $DD. Remember that 
you can find all ASCII codes in Appendix D; look in the column marked 
ASCII. 



So far we have started up our programs with a G (go) command from 
the MLM, and we have terminated our programs with a BRK command 
that returns us to the monitor. That's not a convenient way to run a program; 
most users would prefer to say RUN out of BASIC and have the computer 
do everything. 

We can link to a machine language program from BASIC and when the 
program is finished, it can return to BASIC and allow the BASIC program 
to continue to run. The commands we need are 

(BASIC) SYS— Go to a machine language subroutine at the stated address; 
(Machine language) ETS— Return to whoever called this subroutine. 



Running the Program 




BASIC 



CONTROLLING OUTPUT 



31 



Let's change our machine language program first. We must change the 
BEK at the end to RTS (return from subroutine) so that when the program 
is finished it will return to BASIC. If you like, you may change it directly 
on the disassembly listing: disassemble and then type over the □□ byte 
that represents BEK with a value of bO. Press RETDRN and you'll see 
that the instruction has now changed to RTS. Alternatively, you may re- 
assemble with 

a 033CLDA#$4fl 
a 033E JSR $FFD5 
ft U3A1 RTS 

Now return to BASIC (using the X command). The computer will say 
REftDY; you may now call your program with a SYS command. 

Address $D33CisflEflin decimal. Thus, we type SYS flEfl.Whenwe 
press RETURN, the tetter H will be printed. 

We're not finished. Any machine language subroutine may be called from 
a BASIC program. Type NEW, which clears out the BASIC work area; our 
machine language program is left untouched, since NEW is a BASIC com- 
mand. Now enter the following program: 

FOR J = 1T0 1D 
IID SYS flEfl 
15D NEXT J 

How many times will our program atflEfl($D33C)be called? How many 
times will the letter H be printed? Will they be on the same line or separate 
lines? Type RON and see. 

Project for enthusiasts: Again, change the machine language program 
to say HI. Use your imagination. What else would you like the computer 
to say? Would you like to use colors or reverse font? 

We've achieved an important new plateau: BASIC and machine language 
working together. It's easier on the user, who doesn't have to learn spe- 
cialized monitor commands. It's easier on the programmer, too, since 
things that are easy to do in BASIC can be written in that language; things 
that are clumsy or slow in BASIC can be written in machine language. We 
can get the best of both worlds. 

Let's distinguish our three different types of subroutine calls: 
GOSDB— calls a BASIC subroutine from a BASIC program. 
SYS — calls a machine language subroutine from a BASIC program. 
JSR— calls a machine language subroutine from machine language. 



32 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Loops 

We know how to send characters to the screen, one at a time. But long 
messages, such as THE QUICK BROWN CRT . . ., might lead to te- 
dious coding if we had to write an instruction for each letter to be sent. 
We need to set up a program loop to repeat the printing activity. 

Let's write a program to print the word HELLO followed by a RETURN. 

C128 note: Remember to check Exercises for the Commodore 128, in 
Appendix E, for the appropriate coding. 

We must store the word HELLO somewhere in memory. It doesn't matter 
where, provided it doesn't conflict with anything else. I'll arbitrarily choose 
address $034Ato $Q3AT. We'll put it there in a moment. Remember 
that the characters that make up the word HELLO (plus the RETURN) 
are not program instructions; they are simple data. We must put them in 
place with a memory change — we must not try to assemble them. 

We will need to count the characters as we send them. We wish to send 
six characters, so a count of six is our limit. Let's use the X register to 
keep track of the count. First, we must set X to zero: 

a a33C LDX #$0D 

Note that we use the # symbol to denote an immediate value: we want 
to load X with the value zero, not something from address □. Now, we'll 
do something new. I want to take a character to be printed from address 
$D3<A. But wait, that's only the first time around. When we come back 
to this point in the loop, I want to take a character from $ □ 3 4 B , and then 
from $Q3AC, and so on. 

How can we do this? It seems that we must write one address into the 
LDA instruction, and that address can't change. But there is a way. 

We can ask the computer to take the address we supply, and add the 
contents of X or Y to this address before we use it. The computed address 
is called an effective address. 

Let's look at our position. The first time around the loop, X is counting the 
characters and has a value of zero. If we specify our address as □ 3 ft + X , 
the effective address will be 034 ft. That's where we will have stored the 
letter H. 

When we come back around the loop — we haven't written that part yet — 
X should now equal one. An address of □ 3 4 ft + X would give an effective 
address of 034 B; the computer would go there and get the letter E. As 



CONTROLLING OUTPUT 



33 



we go around the loop, the letters, L, L, 0, and RETURN will be brought 
In as needed. 

As we enter the LD A instruction, we don't type the plus sign. Instead, we 
signal indexing with a comma: LDa$D3<ft,X.We may use either X or 
Y for indexing: they are sometimes called index registers. In this case, of 
course, we use X. So we code 

A n33E LDA$034A,X 
A 03^1 JSR $FFD5 

The first time, the computer loads the contents of address $03 A k (the 
letter H of HELLO) and prints it. When the loop comes back here, with 
X equal to one, this instruction will load the contents of $ 03^6 and print 
the letter E. 

The X register counts the number of letters printed, so we must add one 
to the contents of X. There's a special command that will add one to the 
contents of X: I NX, for increment X. A similar code, I NY, allows Y to 
be Incremented; and DEX (decrement X) and DEY (decrement Y) allow 
X or Y to be decremented, or reduced, by one. At the moment, I NX is 
the one we need for counting: 

A Q3AA INX 

Now we can test X to see if it is equal to six yet. The first time around, it 
won't be since X started at zero and was incremented to a value of 1. If 
X is not equal to six, we'll go back to $D33E and print another letter. 
Here's how we code it: 

A DS^B CPX#$Dt 
A 0347 BNE $D33E 

CPX stands for compare X; note that we are testing for an immediate 
value of six, so we use the # symbol. BNE means branch not equal; if X 
is not equal to six, back we go to address $D33E. 

A little careful thought will reveal that the program will go back five times 
for a total of six times around the loop. It's exactly what we want. 

Let's show the whole code, completing it with RTS: 

A 033C LDX#$QD 

A 033E LDA$D3<A,X 

A 03^1 JSR $FFD2 

A Q3AA INX 

AD3AS CPX#$Qt 

A n3A7 BNE $D33E 

A Q3A^ RTS 



34 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



We may now put the characters for HELLO into memory. These are data, 
not instructions, so we must not try to assemble them. Instead, we change 
memory in the usual way, by displaying and then typing over. We give 
the command M D3<A D3^F, and type over the display to show 

:D3<a A& AS AC AC UJ) XX XX 

By a lucky coincidence, this data fits exactly behind our program. 

Everything should be ready now. Disassemble the program at $D33C 
and check it. You may note that the data at $ □34ft doesn't disassemble 
too well, but that's to be expected; these bytes are not instructions and 
cannot be decoded. 

When all looks well, return to BASIC (with .X) and try SYS flSfl. The 
computer should say HELLO. 

Once again, set up a BASIC loop program: 

!□□ FOR J = 1T0 3 

110 SYS as a 

IBD NEXT J 

A Comment on SAVE 

If you wished to save the program to cassette tape, you'd have a problem 
on the VIC or Commodore 64. The machine language program is in the 
cassette buffer; a save-to-tape command would cause the contents of that 
buffer to be destroyed before the program could be written to tape. Even 
disk commands would not be completely safe: 4.0 BASIC disk commands 
use the cassette buffer area as a work area; using these commands would 
probably destroy our machine language program. 

But saving the program is not the main problem. A correctly saved program 
can give trouble when you try to bring it back and run it safely. The difficulty 
is related to BASIC pointers, especially the start-of-variables pointer. The 
problem, and how to solve it, will be discussed in some detail in Chapter 
6. 

A Stopgap SAVE 

We can presen/e short programs by making them part of DfiTft state- 
ments. The procedure is not difficult if screen editing is used intelligently. 

We note that the program extends from $D33Cto$D3<F, including the 
message (HELLO) at the end. The decimal equivalents to these ad- 
dresses are a 5 a to a < 7 . C1 28 note: Appendix E, in the section Exercises 



CONTROLLING OUTPUT 



35 



for the Commodore 128, will give you the correct addresses and values 
for doing this on the C128. Enter the following BASIC line: 

FOR J = flea TO fl-^? : PRINT PEEK (J) ; :NEXT J 

Study the above line. You will see that it asks BASIC to go through the 
part of memory containing your machine language program, and display 
the contents (in decimal notation, of course). You'll see a result that looks 
something like this: 

ite D laq 3 510 555 533 5E/; y eoa sas qt 

75 7t> 7b m 13 

These are indeed the bytes that make up your program. With a little study, 
you could reconstruct the It5-D combination to be LDX #$□□, or the 
7 E-t R-7 1-7 1-7 q at the end to be the word HELLO in ASCII. It looks 
different when it's in decimal, but it's still the same numbers. 

You may try a little skill and artistry, using screen editing to perform the 
next activity, or you may just retype the numbers into data lines a shown. 
Either way, arrange the numbers as follows: 

50 DATA lt5,D,lflS,74,3,35,21D,255,E32,5S<,t 
tD DATA EDfl/E<5,qt,72,tH,7t,7t,7R,13 

We now have a copy of our program, exactly the way it appears in memory, 
but stored within DATA statements. The DATA statements are part of a 
normal BASIC program, of course, and will SAVE and LOAD with no 
trouble at all. 

We can now reconstruct our machine language program, placing it back 
into memory, with a simple BASIC POKE program: 

an FOR j = flEa TO a^7 : read x:poke J, X: next J 

Now our program is safe and sound — it handles like BASIC, but it will do 
a machine language task for us as desired. Let's display the entire BASIC 
program 

50 DATA lt.3, 0,169, 7^,3, 35, 210,555, 232, S5<,t 

to DATA 50fl,5^5,Rt.,75,tq,?t.,?t,7q,13 

flO FOR J=fl5fl TO fl'!;7 : READ X: POKE J,X:NEXT J 

100 FOR J= 1 TO 3 

110 SYS 350 

150 NEXT J 

This method of saving a machine language program is clean and trouble 
free, but it becomes awkward where long programs are involved. More 
advanced methods will be discussed in Chapter 6. 



36 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Things You Have Learned 

—Subroutines can be called from machine language using the JSR command. 
There are several useful kernal subroutines permanently available. 

—A BASIC program may call a machine language program as a subroutine: 

the BASIC command is SYS. The machine language subroutine returns to 

the calling point with an RTS (return from subroutine) instruction. 
—The CHROUT subroutine at address $FFDE allows output of a character, 

usually to the screen. In addition to printable characters, special cursor- and 

color-control characters may be sent. 
— Most machine language monitors have a small assembler to help program 

preparation, and a disassembler to assist in program checking. 
—Immediate mode Is signaled by use of the # symbol. The computer Is asked 

to take the value given, instead of going to a specified address for its data. 
—X and Y are called index registers. We may add the contents of X or Y to a 

specified address, to create an effective address that changes as the program 

runs. This addition Is called indexing. 
— X and Y also have special instructions that increase or decrease the selected 

register by one. These are called increment and decrement instructions, and 

are coded INX, INY, DEX, and DEY. 

Questions and Projects 

Look through the table of ASCII characters in Appendix D. Note that hex 
13 Is "clear screen." Write a program to clear the screen and print "HO 
HO! ". 

You may have noticed that in our example, we had register X counting 
up from zero to the desired value. What would happen if you started X at 
5 and counted down? Try it if you like. 

Remember that you can also include cursor movements, color codes (if 
your machine has color), and other special ASCII characters. Could you 
lay out the coding to draw a box? (Try it in BASIC first). Draw a box with 
the word HELLO inside it. 



3 



Flags, Logic, 
and Input 

This chapter discusses: 

• Flags that hold status information 

• Testable flags: Z, C, N, and V 

• Signed numbers 

• The status register 

• First concepts of interrupt 

• Logical operators: OR, RND, EOR 

• The GE TIN subroutine for input 

• The STOP subroutine 



39 



40 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Flags 

Near the end of Chapter 2, we coded a program that had the seemingly 
natural sequence 

CPX #$0t 
BNE $ . . . . 

It made sense: compare X for a value of t, and if not equal, branch back. 
Yet it implies something extraordinary; the two instructions are somehow 
linked. 

Let's flash fonward for a moment. Even when you have a machine language 
program running, the computer "freezes" sixty times a second. The com- 
puter undertakes a special activity, called interrupt processmg. It stops 
whatever it was doing, and switches to a new set of programs that do 
several tasks: flashing the cursor, checking the keyboard, keeping the 
clock up to date, and checking to see whether the cassette motor needs 
power. When it's finished, it "unfreezes" the main program and lets it 
continue where it left off. 

This interrupt might take place between the two instructions shown above, 
that is, after the CPX and before the BNE. Hundreds of interrupt instruc- 
tions might be executed between the two, yet nothing is harmed. The two 
instructions work together perfectly to achieve the desired effect. How can 
the compiL|ter do this? 

The two instructions are linked by means of a flag— a part of the 650x 
that records that something has happened. The CPX instruction tests X 
and turns a special flag on or off to signal how the comparison turned out: 
equal or unequal. The BNE instruction tests that flag. If it's on (meaning 
equal), no branch will take place and the program will continue with the 
next instruction; if it's off (meaning not equal), a branch will take place. 

In other words, some instructions leave a "trail" of status information; other 
instructions can check this information. The status information is called 
"flags." There are four flags that may be tested: Z, C, N, and V. They are 
discussed below. 

Z Flag 

The Z (zero) flag is probably misnamed, and should have been called the 
E flag (for "equals"). After any comparison (CPX to compare X, CPY to 
compare Y, or CMP to compare R), the Z flag will be set to "on" if the 
compared values are equal; othenwise it will be reset to "off." 



FLAGS. LOGIC. AND INPUT 



41 



Sometimes the Z flag checks for equal to zero, hence its name, Z for 
zero. This happens for every activity that may change one of the three 
data registers. Thus, any load command will affect the Z flag status. The 
same is true of increment and decrement instructions, which obviously 
change registers. And later, when we meet other operations such as ad- 
dition and subtraction, they too will affect the Z flag. 

There are many instructions that don't affect the Z flag (or any flag, for 
that matter). Store instructions (STR, STX, STY), never change a flag. 
Branch instructions test flags but don't change them. 

An example will help illustrate the way that some instructions change flags 
and others do not. Examine the following coding: 

LDA #$53 (Load 53 to A) 
LDX #$□□ (Load zero to X) 
STa$153< (store 53 to address $1534) 
BEQ$ 

Will the branch (BEQ) be taken, or will the 650x continue with the next 
instruction? Let's analyze the Z flag's activity step by step. The first in- 
struction (LDA #$53) resets the Z flag, since 53 is not equal to zero. 
The second instruction (LDX #$□□) sets the Z flag because of the zero 
value. The third instruction (STA $1534) does not affect the Z flag; in 
fact, store instructions do not affect any flags. Thus, by the time we reach 
the BEQ instruction, the Z flag is set "on" and the branch will be taken. 

650x reference manuals show the specific flags that are affected by each 
instruction. In case of doubt, they are easy to check. 

The Z flag is quite busy — it clicks on and off very often since many in- 
structions affect it. It's an important flag. 

If the Z flag is set "on," the BEQ (branch equals) instruction will branch 
to the specified address; othenwise it will be ignored and the next instruction 
in sequence will be executed. If the Z flag is reset "off," the BNE (branch 
not equals) instruction will branch. 

We can see in more detail how our program from Chapter 2 worked. 
CPX #$Dt causes the Z flag to be set "on" if X contains the value t; 
othenwise it causes the Z flag to be reset "off." BNE tests this flag, and 
branches back to the loop only if the Z flag is off — in other words, only If 
the contents of X is not equal to six. 



42 



MACHINE LANGUAGE FOR COMMODORE' MACHINES 



C Flag 

The C (carry) flag is probably misnamed, too. It should have been called 
the GE (greater/equal) flag, since after a comparison (CP X, CP Y, or CMP), 
the C flag is set "on" if the register (X, Y, or A) is greater than or equal 
to the value compared. If the register concerned is smaller, the C flag will 
be reset "off." 

The C flag is not as busy as the Z flag. The C flag is affected only by 
comparison instructions and by arithmetic activities (add, subtract, and a 
type of multiplication and division called rotate or shift). When used in 
arithmetic, the C flag is properly named, since it acts as a "carry" bit 
between various columns as they are calculated. For example, an LDR 
instruction always affects the Z flag since a register is being changed, but 
never affects the C flag since no arithmetic or comparison is being per- 
formed. 

If the C flag is set "on," the BCS (branch carry set) instruction will branch 
to the specified address; otherwise it will be ignored and the next instruction 
in sequence will be executed. If the C flag is reset "off," the BCC (branch 
carry clear) instruction will branch. 

The C flag may be directly set or reset by means of the instructions SEC 
(set carry) and CLC (clear carry). We will use these instructions when we 
begin to deal with addition and subtraction. 

If you examine the last program of Chapter 2, you will see that the BNE 
instruction could be replaced by BCC. Instead of "branch back if not equal 
to 6," we could code "branch bacl< if less than 6." The operation would 
be the same in either case. 

N Flag 

The N (negative) flag is also probably misnamed. It should have been 
called the HB (high bit) flag, since numbers are positive or negative only 
if they are used in a certain way. The N flag is set to indicate that a register 
has been given a value whose high bit is set. 

The N flag is as busy as the Z flag; it changes with every instruction that 
affects a register. The N flag is affected by comparisons, but in this case 
its condition is not usually meaningful to the programmer. 

To sort out the operation of the N flag, it's important to become familiar 
with hexadecimal-to-binary conversion. For example, will LDR #$b5 set 
the N flag? Rewrite it into binary: $ 1 5 equals ^ □ 1 1 □ □ 1 □ 1 . We can see 



FLAGS, LOGIC, AND INPUT 



43 



that the high bit is not set, meaning that the N flag will be off after loading 
this value. As another example, suppose we LDX #$Da. Hex Dfi is 
IIDIIDID binary. We see that the high bit is on and thus the N flag is 
set. 

If the N flag is set "on," the BMI (branch minus) instruction will branch 
to the specified address; othenwise it will be ignored and the next instruction 
in sequence will be executed, if the N flag is reset "off," the BPL (branch 
plus) instruction will branch. 

A Brief Diversion: Signed Numbers 

How can a location— which is usually thought to contain a decimal value 
from □ to E55 — contain a negative number? It's up to the programmer 
to decide whether a memory value is unsigned, having a value range from 
to 555, or signed, having a value range from -15flto+127. There 
are still a total of E5t possibilities. The computer's memory simply holds 
bits, while the programmer decides how the bits are to be used in a specific 
case. 

IVIathematically, it's described this way: signed numbers, if desired, are 
held in two's-complement form. We can hold - 1 as hex FF, and - 2 
as hex FE, all the way down to - 1 2 fl as hex fl 0. You may have noticed 
that in all the examples, the high bit is set for these negative numbers. 

We may need more intuitive help, however. If the computer loads the 
decimal value 2DD into the A register with LDA #$Cfl, the N flag will be 
set and will seemingly indicate that E D □ is a negative number. It may be 
more comfortable to simply thini< of SDD as a number with the high bit 
set. But in a sense, EDO could be a negative number if we wanted it to 
be. Let's examine the situation by means of examples. 

If I were asl<ed to count down in hexadecimal from !□, I'd start out $!□, 
$DF,$DE,and$DD, continuing down to $ □ E , $ □ 1 , and $ □ □ . If I needed 
to keep going, I'd continue past $00 with $FF; in this case, hex FF would 
clearly represent negative one. Continuing, FE, FD, and FC would rep- 
resent -E, -3, and - A. And the high bit is set on all these "negative" 
numbers. 

Let's discuss a decimal analogy. Suppose you have a cassette recorder 
with a counter device attached, and the counter reads 0025. If you rewind 
the unit a distance of 30 units, you would not be surprised to see a value 
of 9995 on the counter and would understand that it meant a position of 
-5. If you had a car with 1 ,500 miles on the odometer, and "rolled back" 



44 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



the mileage by 1 ,501 miles, you'd see a reading of 99999, whicli would 
mean - 1 . (The author does not know this from personal experience, but 
is assured by many machine language students that it is so.) In these 
cases, based on the decimal system, the negative numbers are called 
"ten's complement." 

V Flag 

As with the other flags, the V (overflow) flag is probably misnamed. It 
should have been called the SAO (signed arithmetic overflow) flag, since 
it is affected only by addition and subtraction commands, and is meaningful 
only if the numbers concerned are considered to be signed. 

The V flag is used only occasionally in typical 650x coding. Many machine 
language programs don't use signed numbers at all. The most typical use 
of the V flag is in conjunction with a rather specialized command, BIT 
(bit test). For this instruction, the V flag signals the condition of bit t of 
the memory location being tested. In this case, V and N work in a similar 
way: N reflects the high bit, bit 7, and V represents the "next bit down," 
bit b. The BIT command is used primarily for testing input/output ports 
on I A (interface adaptor) chips. 

If the V flag is set "on," the BVS (branch overflow set) instruction will 
branch to the specified address; otherwise it will be ignored and the next 
instruction in sequence will be executed. If the V flag is reset "off," the 
BVC (branch overflow clear) instruction will branch. 

The V flag may be directly reset by means of the CLV (clear overflow) 
instruction. Oddly, there is no equivalent instruction to set the flag. 

One special feature of the V flag: on some 650x chips, the V flag can be 
set by hardware. There is a pin on the chip that can be used so that an 
external logic signal will trigger the V flag. 

A Brief Diversion: Overflow 

The term overflow means "the result is too big to fit." For example, if I 
add eOD to EDO, the total is ^^DO ... but this won't fit in a single byte. 
If we have only a single byte to store the result, we say that the addition 
has encountered overflow, and we can't produce a meaningful answer. 

If we are using unsigned numbers, the C flag tells us about overflow. If 
we are using signed numbers, V tells the story. We'll take this up again 
in the next chapter. 



FLAGS, LOGIC, AND INPUT 



45 



Flag Summary 



A brief table may help review the four testable flags. 



Flag Brief Activity 
Name Meaning Level 



Branch Taken If: 
Set Not-Set 



Z Zero, equal Busy 

C Carry, greater/equal Quiet 

N Negative, high-bit Busy 

V Signed arithmetic overflow Quiet 



BEQ BNE 

ECS BCC 

BMI BPL 

BVS BVC 



The Status Register 



The preceding flags— and three others— may be viewed within the status 
register (SE). You may recall that the machine language monitor gives 
an SR display. If you know how to read it, you can see the condition of 
all flags. 

Each flag is a bit within the status register. Again, it's useful to be able to 
easily translate the hexadecimal display, so as to view the individual flags. 
Here's a chart of the flags within the status register: 

NV-BDIZC 
Taking the bits one at a time, starting at the high bit: 

N— the N flag, as above 
V — the V flag, as above. 

Bit 5— unused. You'll often find that this bit is "on." 

B— "Break" indicator. When an interrupt occurs, this signals whether or not the 
interrupt was caused by a BRK instruction. 

D— Decimal mode indicator. This changes the manner in which the add and 
subtract instructions operate. In Commodore machines, this flag will always be 
off. Don't turn it on unless you know exactly what you're doing. This flag may 
be turned on with the SED (set decimal) instruction, and turned off with the 
OLD (clear decimal) instruction. 

I— Interrupt disable. More exactly, this bit disables the IRQ (interrupt request) 
pin activity. More on this control bit much later. This flag may be turned on with 
the SEI (set interrupt disable) instruction, and turned off with the CLI (clear 
interrupt disable) instruction. 

Z — the Z flag, as above. 

C — the C flag, as above. 



46 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Flags B, D, and I are not testable flags in that there are no branch instructions 
that test them directly. D, the decimal mode flag, and I, the interrupt locl<out 
flag, may be considered "control" flags. Instead of reporting conditions found 
as the program runs, they control how the program operates. 

When we see a value displayed in the SR, or status register, we may 
examine it to determine the condition of the flags, especially the testable 
flags Z, C, N, and V. For example, if we see an SR value of $B1, we 
translate to binary ^IDllODDl and know that the N flag is on, the V 
flag is off, the Z flag is off, and the C flag is on. 

You may change these flags by typing over the displayed value in the 
machine language monitor. Be careful you don't accidentally set the D or 
I flags. 

A Note on Comparison 

If we wish to compare two bytes with each other, we must perform a 
comparison. One value must be in a register (ft, X, or Y); the other must 
either be stored in memory, or must be an immediate value we use in the 

instruction. 

We will use the appropriate compare instruction depending on the register 
involved; CMP for the ft register, CPX for the X register, and CPY for the 
Y register. Following the comparison, we may use any of the following 
branch tests: 

BE Q— branches if the two bytes are equal. 
BNE— branches if the two bytes are not equal. 

BCS— branches if the value in the register is greater than or equal to the other 
value. 

BCC — branches if the vaiue in the register is iess than the other value. 

We can use more than one branch instruction after a comparison. Suppose 
our program wanted to test the Y register for a value equal to or less than 
5. We might code 

CPY #$05 

BEQ - . somewhere 

BCC . . somewhere 

We can see that our code will branch if the value is equal to 5 (using the 
BEQ) or less than 5 (using the BCC); othenwise it will continue without 
branching. In this case, we could make the coding more efficient by chang- 
ing it to read 



FLAGS, LOGIC, AND INPUT 



47 



CPY #$Dt 

BCC . . somewhere 

A little common sense will tell us that testing a number to see if it is less 
than h is the same as testing it to see if it is less than or equal to S. 
Common sense is a valuable programming tool. 



We have looked at the three data registers — ft, X, and Y — and have seen 
three types of operation we can perform with them: 



Compare: CMP, CPX, CPY 

Up to this point, the registers have identical functions, and we can use 
any of them for any of these functions. But new instructions are creeping 
in that give a different personality to each of the three. 

We have noted that INX, INY, DEX, and DEY for increment and dec- 
rement are restricted to X and Y only; and we've also mentioned that X 
and Y can be used for indexing. Soon, we'll start to examine some of the 
functions of the A register, which is often called the accumulator because 
of its ability to do arithmetic. 

We have seen JSR, which allows us to call a subroutine of prewritten 
instructions. We've used RTS, which says, "Go back to the calling point," 
even if the calling point is a BASIC program. And we've almost abandoned 
the BRK instruction, which stops the program and goes to the machine 
language monitor. BRK will be useful in checking out programs. Specifi- 
cally, we can stop a program at any time by inserting a BRK instruction, 
allowing us to see whether the program is behaving correctly and whether 
it has dorle the things we planned. 

There are eight branch instructions. They have already been discussed, 
but there is one additional piece of information that is important to keep 
in mind. All branches are good only for short hops of up to a hundred 
memory locations or so. So long as we write short programs, that won't 
be a limitation; but we'll look at this more closely in Chapter 5. 



Three instructions perform what are called logical operations. They are: 
AND (Logical AND); ORA (Logical OR); and EOR (Exclusive OR). These 
instructions work on the A register only. 



Instructions: A Review 



Load: 
Store: 



LDA, LDX, LDY 
STA, SIX, STY 



Logical Operators 



48 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Mathematicians describe these operations as commutative. For example, 
a value of $3ft "AND" $57 gives exactly the same result as $57 
"AND" $3 A. The order doesn't matter. But we often use these func- 
tions — and thinl< of them — in a particular order. It's the same as with 
addition, where we think of a "total" to which is added an "amount" to 
make a "new total." With the logical operators we often think of a "value," 
which we manipulate with a "mask" to make a "modified value." 

Logical operators work in such a way that each bit within a byte is treated 
independently of all the other bits. This makes these instructions ideal for 
extracting bits, or manipulating certain bits while leaving others alone. 

We'll look at formal definitions, but the following intuitive concepts are 
useful to programmers: 

AND — turns bits off. 
OEA — turns bits on. 
EOR — flips bits over. 

AUD— Logical AND to A 

For each bit in the A register, AND performs the following action: 

Original A Bit Mas/f Resuiting A Bit 

□ 

1 □ □ 
□ 1 □ 
1 1 1 

Examine the upper half of this table. When the mask is zero, the original 
bit in A is changed to zero. Examine the lower half. When the mask is 
one, the original bit is left unchanged. Hence, AND can selectively turn 
bits off. 

Example: Turn off bits A, 5, and t in the following value: $C7 

Original value: llODOlll 

Mask: AND IDDailll (hex flF) 



Result IDDDDlll 

XXX 

Note that the bits marked have been forced to "off," while all other bits 
remain unchanged. 



FLAGS, LOGIC, AND INPUT 49 



OR A— Logical OR to A 

For each bit in the ft register, OR ft performs the following action: 
Original A Bit Mas/c Resulting fl Bit 

□ □ □ 
1 □ 1 

□ 1 1 
111 



Examine the upper half of this table. When the mask is zero, the original 
bit in A is left unchanged. Examine the lower half. When the mask is one, 
the original bit is forced to "on." Hence, OR ft can selectively turn bits on. 

Example: Turn on bits A, S, and t in the following value: $C7 
Original value: llDDDlll 
Mask: ORA DlliaaDD (hex ?□) 

Result 11110111 

XXX 

Note that the bits marked have been forced to "on," while all other bits 
remain unchanged. 

EOR— Exclusive OR to A 

For each bit in the A register, EOB performs the following action: 

Original A Bit Mask Resulting A Bit 

□ □ □ 

10 1 
Oil 
110 

Examine the upper half of this table. When the mask is zero, the original 
bit in A is left unchanged. Examine the lower half. When the mask Is one, 
the original bit is inverted; zero becomes one and one becomes zero. 
Hence, EOR can selectively flip bits over. 

Example: Invert bits A, 5, and t in the following value: $C7 
Original value: 11000111 
Mask: EOR 01110000 ( hex 70 ) 



Result 



lOllDlll 



50 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Note that the bits marked have been flipped to the opposite value, while 
all other bits remain unchanged. 

Why Logical Operations? 

We use these three commands— ft ND, ORft, and EOR— to change or 
control individual bits within a byte of information. The commands are 
unusual in that each bit may be manipulated independently of the others. 

We don't seem to be working with numbers when we use these commands. 
Rather, we're working with each individual bit, turning it on or off as we 
wish. 

Why would we turn individual bits on or off? There are several possible 
reasons. For example, we might wish to control external devices through 
the Ift's (interface adaptors). Within the Ift's input and output ports each 
of the eight bits might control a different signal; we might want to switch 
one control line on or off without affecting other lines. 

When we're looking at input from an I ft port, we often read several input 
lines mixed together within a byte. If we want to test a specific bit to see 
if it is on or off, we might mask out all other bits with the ftND instruction 
(changing unwanted bits to zero); if the remaining bit is zero, the whole 
byte will now be zero and the Z flag will be set. 

Why would we want to flip bits over? Many "oscillating" effects— screen 
flashing or musical notes— can be accomplished this way. 

Finally, the logical operators can be useful in code translation. For ex- 
ample, here are the values for ASCII 5 and binary 5: 

ASCII fOOllDlDl 
Binary ^OODODlOl 

We must use the ASCII value for input or output. We must use the binary 
value for arithmetic, particularly addition and subtraction. How could we 
get from one to the other? By taking bits out (RND) or putting bits in (ORR). 
Alternatively, we could use addition or subtraction; the logical operators, 
however, are simplier. 

Input: The GE T I N Subroutine 

We have seen how we can use CHROUT at $FFD2 to produce output 
to the screen. Now we'll look at the input side— how to use the GETIN 
subroutine at $FFE4 to get characters from the keyboard buffer. 



FLAGS, LOGIC, AND INPUT 



51 



You may be familiar witli tlie GET statement in BASIC. If so, you'll find 
the same characteristics in GETIN: 

• Input is taken from the keyboard buffer, not the screen. 

• If a key Is held down, it will still be detected once only. 

• The subroutine returns immediately. 

• If no key is found, a binary zero is returned in A. 

• If a key is found, its ASCII value will be in A. 

• Special keys, such as RETURN, RVS, or color codes, will be detected. 

To call for a key from the keyboard, code JSR $FFE4. Values in X and 
Y are not guaranteed to be preserved, so if you have important information 
in either register, put it away into memory. 



Subroutine: GETIN 
Address: SFFE-^ 

Action: Takes a character from the input channel and places it 

into the A register. The input channel is the keyboard input 
buffer unless arrangements have been made to switch it. 

The character received is usually ASCII (or PET ASCII). When read 
from the keyboard, the action is similar to a BASIC GET statement: 
one character will be taken from the buffer; it will not be shown on the 
screen. If no character is available from the keyboard input buffer, a 
value of binary zero will be put into the A register. The subroutine will 
not wait for a key to be pressed but will always return immediately. 

Registers: The A register will of course always be affected. X and Y 
are likely to be changed; do not have data in these when calling 
GETIN. 

Status: Status flags may be changed. In most recent Commodore 
machines, the C (carry) flag indicates some type of problem with input. 



If we want keyboard input to appear on the screen, we should follow a 
call to GETIN, $FFE4, with a call to CHRODT, $FFD2, so that the 
received character is printed. 

STOP 

Machine language programs will ignore the RUN/STOP key . . . unless 
the program checks this key itself. It may do so with a call to STOP, 
address $FFE1. This checks the RUN/STOP key at that moment. To 
make the key operational, $FFE1 must be called frequently. 



52 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



A call to FFEl should be followed by a BEQ to a program exit so that 
the program will terminate when RUN/STOP Is pressed. 

The RON/STOP key is often brought Into play while programs are being 
tested, so that unexpected "hangups" can still allow the program to be 
terminated. Coding to test the RUN/STOP key is often removed once 
testing is complete, on the assumption that no one will want to stop a 
perfect program. Incidentally, if you plan to write nothing but 100 percent 
perfect programs, you will not need to use this subroutine. 



Subroutine: STOP 
Address $FFE1 

Action: Check the EUN/STOP key. If RDN/STOP is being pressed 

at that instant, the Z flag will be set when the subroutine 
returns. 

In PET/CBM, the system will exit to BASIC and say READY if the 
RUN/STOP key is being pressed. In this case, it will not return to the 
calling machine language program. 

Registers: A will be affected. X will be affected only if the RUN/STOP 
key is being pressed. 

Status: Z signals whether RUN/STOP is being pressed. 



Programming Project 

Here's our task: we wish to write a subroutine that will wait for a numeric 
key to be pressed. All other keys (except RUN/STOP) will be Ignored. 

C128 note: Remember to check Appendix E, under Exercises for the 
Commodore 128, for the appropriate coding. 

When a numeric key is pressed, it will be echoed to the screen, and then 
the subroutine will be finished. One more thing. The numeric character 
will arrive in ASCII from the keyboard: we wish to change It to a binary 
value before giving the final RTS statement. This last operation has no 
useful purpose yet, except as an exercise, but we'll connect it up in the 
next chapter. 

Coding sheets ready? Here we go. 
A 0330 JSR $FFE1 

We will check the RUN/STOP key first. But wait. Where will we go if we 
find that the key is pressed? To the RTS, of course; but we don't know 



FLAGS, LOGIC, AND INPUT 



53 



where that is, yet. In these circumstances, we usually make a rough guess 
and correct it later. Make a note to check this one . . . 

A 0337 BEQ $0351 
a D3A1 JSR $FFE4 

Now we've gotten a character; we must check that it's a legitimate numeric. 
The ASCII number set to "=1 has hexadecimal values $3 □ to $31. So 
if the value is less than $3 0, it's not a number. How do we say "less 
than?" After a compare, it's BCC (branch carry clear). So we code 

A U3AA CMP #$3D 
a 034t. BCC $D33C 

Did you spot the use of immediate mode at address $U3AA7 Make sure 
you follow the logic on this. Another point: what if no key has been pressed? 
We're safe. There will be a zero in the a register, which is less than hex 
3D; this will cause us to go back and try again. 

Now for the high side. If the number is greater than hex 3R, we must 
reject it since it cannot be an ASCII numeric. Our first instinct is to code 
CMP #$39 and BCS. But wait! BCS (branch carry set) means "branch 
if greater than or equal to." Our proposed coding would reject the digit =1, 
since the carry flag would be set when we compared to a value of hex 

3q. 

We must check against a value that is one higher that $3R. Be careful, 
though, for we're in hexadecimal. The next value is $3 a. Code it: 

a Q3A& CMP #$3a 
a □3<a BCS $D33C 

If we get this far, we must have an ASCII character from □ to 'I ; let's print 
it to the screen so that the user gets visual feedback that the right key 
has been pressed: 

a D3AC JSR $FFDE 

Now for our final task. We are asked to change the ASCII character into 
true binary. We may do this by knocking off the high bits. We remember, 
of course, that to turn bits off we must use aND: 

a D3AF aND #$DF 
a 0351 RTS 

It's a good thing that we printed the character first, and then converted to 
binary; the character must be ASCII to print correctly. 



54 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



One last thing. We had a branch (on the RUN/STOP key) that needed to 
connect up with the RTS. Did you mal<e that note about going bacl< and 
fixing up the branch? Now is the time to do it, but before you go bacl<, 
terminate the assembly with an extra RETURN on the keyboard (the 
assembler gets confused if it prompts you for one address and you give 
andther; get out before you go back). 

By a fortunate stroke of luck, we happen to have guessed the right address 
for the BE Q at address $ □ 3 3 F. But if we hadn't, you know how to change 
it, don't you? 

Check your coding, disassemble, go back to BASIC and run with a SYS 
flEfl. Tap a few letter keys and note that nothing happens. Press a num- 
ber; and see it appear on the screen. The program will terminate. SYS it 
again and see if the RUN/STOP works. Try a BASIC loop to confirm that 
BASIC and machine language work together. 

Project for enthusiasts: Try modifying the program so that it checks for 
alphabetic characters only. Alphabetic characters run from $<1 to $5A, 
inclusive. 

Things You Have Learned 

—Flags are used to link instructions together. This might be an activity such 
as load or compare, followed by a test such as branch on a given condition. 

— Some instructions affect one or more flags, and some do not affect flags. 
Thus, an instruction that sets a flag might not be followed immediately with 
the instruction that tests or uses that flag. 

— There are four testable flags: Z (zero, or equals); C (carry, or greater/equal); 
N (negative, or high bit); and V (signed arithmetic overflow). The flags are 
checked by means of "branch" instructions such as BEQ (branch equal) or 
BNE (branch not equal). 

— Flags are stored in the status register, sometimes called the processor status 
word. The S B contains the four testable flags, plus three other flags: B (break 
indicator); D (decimal mode for add/subtract); and I (interrupt lockout). The 
hexadecimal value in SB can be changed to binary and used to determine 
the exact condition of all flags. 

— Usually, the processor is interrupted sixty times a second to do special high- 
priority jobs. Everything, including the status register flags, is carefully pre- 
served so that the main program can continue as though nothing had 
happened. 

— A number stored in memory can be considered as signed if we decide to 
handle it that way. The value of a signed number is held in two's-complement 
form. The high bit of the number is zero if the number is positive, one if the 



FLAGS, LOGIC, AND INPUT 



55 



number is negative. Tlie computer doesn't care. It handies tlie bits wfiether 
the number is considered signed or not, but we must write our program 
l<eeping in mind tlie type of number being used. 

— Tfiere are tliree logical operator instructions: AND, ORA, and EOR. Tliese 
allow us to modify bits selectively within the A register. AND turns bits off; 
ORA turns bits on; and EOR inverts bits, or flips them over. 

Questions and Projects 

Write extra coding to allow both numeric and alphabetic characters, but 
nothing else. 

Write a program to accept only alphabetic characters. As each ASCII 
character is received, turn on its high bit with ORfl #$flD and then print 
it. How has the charactef- been changed? 

Write a program to accept only numeric digits. As each ASCII character 
is received, turn off its lowest bit with AND #$FE and then print it. What 
happens to the numbers? Can you see why? 



4 



Numbers, 
Arithmetic, 
and 

Subroutines 

This chapter discusses: 

• Numbers: signed and unsigned 

• Big numbers: multiple bytes 

• Arithmetic: add and subtract 

• Rotate and shift instructions 

• IVIultlplication 

• Home grown subroutines 



57 



58 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Numbers: Signed and Unsigned 

We have looked briefly at the question of signed versus unsigned numbers. 
The most important concept is that you, the programmer, choose whether 
or not a number is to be considered a signed number (for a single byte, 
in the decimal range -12fl to +1E7) or an unsigned integer (single- 
byte range □ to 555). 

It makes no difference to the computer. If you consider a number signed, 
you may wish to test the sign using the N flag. If not, you won't do such 
a test. 

Big Numbers: Multiple Bytes 

You may use more than one byte to hold a number. Again, it's your 
decision. If you think the numbers may go up to a million, you might allocate 
three bytes (or more or fewer). If you are doing arithmetic on multi-byte 
numbers, the computer will help you by signaling in the carry flag that 
there's something to be carried across from a lower byte to a higher one. 
But it's up to you to write the code to handle the extra bytes. 

You may size numbers by using the following table: 

Unsigned: Signed: 

1 byte to 255 -128 to +127 

2 bytes to 65,535 -32768 to +32767 

3 bytes to 16,777,215 - 8,388,608 to + 8,388,607 

4 bytes to over 4 billion -2 billion to +2 billion 

It's possible to work with binary fractions, but that is beyond the scope of 
this book. Many applications "scale" numbers, so that dollar-and-cents 
amounts are held as integer quantities of pennies. Thus, two bytes un- 
signed would hold values up to $fc55,35, and three bytes up to 
$lt7,7?E.15. 

When signed numbers are held in multiple bytes, the sign is the highest 
bit of the highest byte only. 

We will concentrate on single-byte arithmetic principles here, touching on 
multiple-byte numbers as a generalization of the same ideas. 

Addition 

Principles of addition are similar to those we use in decimal arithmetic; 
for decimal "columns," you may substitute "bytes." Let's look at a simple 
decimal addition: 



NUMBERS, ARITHMETIC, AND SUBROUTINES 



59 



Rule 1 : We start at the right-hand column (the low-order byte). 

Rule 2: We add the two values, plus any carry from the previous column. A new 
carry may be generated; it can never be greater than one. (ADC includes any 
carry from a previous activity, and may generate a new carry bit, which is either 
or 1.) 

Rule 3: When we start at the right-hand column, there is no carry for the first 
addition. (We must clear the carry with CLC before starting a new addition.) 
Rule 4: When we have finished the whole addition, if we have a carry and no 
column to put it in, we say the answer "won't fit." (If an addition sequence of 
unsigned numbers ends up with the carry flag set, it's an overflow condition.) 



HIGH BYTE 



00101011 
00001010 



LOW BYTE 



10111001 y 
11100101 X 



START: 
NO CARRY 



00110110 



/ 

CARRY 

/ 



10011110 



Figure 4.1 



How do we translate these rules into machine language addition? 

1 . Before we start an addition sequence, clear the carry with CLC . 

2. If the numbers are more than one byte in size, start at the low byte and work 
up to the high ones. Addition will take place in the A register only; you may 
add the contents of an address or an immediate value. The carry flag will 
take care of any carries. 

3. When the addition sequence is complete, check for overflow: 

a) If the numbers are unsigned, a set C flag indicates overflow; 

b) if the numbers are signed, a set V flag indicates overflow. 

Thus, to add two unsigned numbers located at addresses $D3fiD and 
$□361 and to place the result at $ 033 5, we might code 



60 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



CLC 

LDa $D3flD 
RDC $03ai 
STft $D3flE 

We might also BCS to an error routine, If desired. 

To add a two-byte number located at $ □3RD (low) and $D3ftl (high) 
to another two-byte number located at $D3Bn (low) and $ 0381 (high), 
placing the result at $D3CD/1, we might code 

CLC 

LDa $D3ftD 
aDC $D3BD 

STa $D3cn 
LDa $D3ai 

aOC $03B1 
STa $D3C1 

Again, we might BCS to an overflow error routine. 

If we had two-byte signed numbers in the same locations, we'd add them 
exactly the same way, using the same code as above. In this case, how- 
ever, we'd check for overflow by adding the instruction BVS, which would 
branch to an error routine. The carry flag would have no meaning at the 
end of the addition sequence. 

Subtraction 

Subtraction might be defined as "upside down" addition. The carry flag 
again serves to link the parts of a multibyte subtraction, but its role is 
reversed. The carry flag is sometimes called an "inverted borrow" when 
used in subtraction. Before performing a subtraction, we must set the C 
flag with SEC. If we are worried about unsigned overflow, we look to 
confirm that the carry is set at the completion of the subtraction operation. 
If the carry is clear, there's a problem. 

Thus, to perform a subtraction, we follow these rules: 

1. Before we start a subtraction sequence, set the carry with SEC. 

2. If the numbers are more than one byte in size, start at the low byte and^work 
up to the high ones. Subtraction will take place in the ft register only; you 
may subtract the contents of an address or an Immediate value. The C flag 
will take care of any "borrows." 

3. When the subtraction sequence is complete, check for overflow: 
a) if the numbers are unsigned, a clear C flag indicates overflow; 



NUMBERS, ARITHMETIC, AND SUBROUTINES 



61 



b) if the numbers are signed, a set V flag indicates overflow. 

Thus, to subtract two unsigned numbers located at addresses $D3flD 
and $ 0361 and to place the result at $ DBA 5, we might code 

SEC 

LDfi $D3fiO 
SBC $D3fll 
STa $U3&E 

A BCC could go to an error routine. 

Comparing Numbers 

if we have two unsigned numbers and wish to know which one is larger, 
we can use the appropriate compare instruction— CMP, CPX, or CPY— 
and then check the carry flag. We've done this before. If the numbers are 
more than one byte long, however, it's not quite so easy. We must then 
use a new technique. 

The easiest way to go about such a comparison is to subtract one number 
from the other. You need not keep the result; all you care about is the 
carry flag when the subtraction is complete. If the C flag is set, the first 
number (the one you are subtracting from) is greater than or equal to the 
second number. Why? Because carry set indicated that the unsigned 
subtraction was legal; we have subtracted the two numbers and have 
obtained a positive (unsigned) result. On the other hand, if the C flag ends 
up clear, this would mean that the first number is less than the second. 
The subtraction couldn't take place correctly since the result— a negative 
number — can't be represented in unsigned arithmetic. 

Left Shift: Multiplication by Two 

If we write the decimal numbers and EDO in binary, we see an 
interesting pattern: 

EDO: ^IIODIDDO 

To double the number, each bit has moved one position to the left. This 
makes sense, since each bit has twice the numeric "weight" of the bit to 
its right. 

The command to multiply a byte by two is ASL (arithmetic shift left). A 
zero bit is pushed into the low (or "right") side of the byte; all bits move 



62 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



left one position; and tlie bit that "falis out" of tlie byte— in this case, a 
zero bit— moves into the carry. It can be diagrammed iil<e this: 



IN AN ASL (ARITHMETIC SHIFT LEFT), EACH BIT 
MOVES ONE POSITION LEFT. A ZERO MOVES INTO THE 
LOW-ORDER BIT. 

Figure 4.2 

That's good for doubling the value of a single byte, if a "one" bit falls into 
the carry flag, we can treat that as an overflow. What about multiple bytes? 

It would be ideal if we had another instruction that would worl< just lil<e 
aSL. Instead of pushing a zero bit into the right hand side of the byte, 
however, it would push the carry bit, that is, the bit that "fell out" of the 
last operation. We have such an instruction: ROL. 

ROL (rotate left) works exactly iil<e ASL except that the carry bit is pushed 
into the next byte. We can diagram it as follows: 



CARRY 

IN A ROL (ROTATE LEFT), THE CARRY MOVES INTO 
THE LOW ORDER BIT; EACH BIT MOVES LEFT; AND THE 
HIGH ORDER BIT BECOMES THE NEW CARRY. 

Figure 4.3 

Thus, we can hook two or more bytes together. If they hold a single 
multibyte number, we can double that number by starting at the low-order 
end. We ASL the first value and ROL the remainder. As the bits fall out 
of each byte, they will be picked up in the next. 



Multiplying by two may not seem too powerful. We can build on this starting 
point, however, and arrange to multiply by any number we choose. 



CARRY 
(C FLAG) 




ASL 




CARRY 



Multiplication 



NUMBERS, ARITHMETIC, AND SUBROUTINES 



63 



ROL 



fi 



ASL 

, , H + 

ROL r-[I^^^3-^ LOW ORDER BYTE 

■ - - > -h c 



HIGH ORDER BYTE 

TO MULTIPLY A THREE-BYTE NUMBER BY TWO, WE 
SHIFT THE LOW ORDER BYTE WITH ASL; THEN WE USE 
ROL TO ALLOW THE C FLAG TO "LINK" FROM ONE 
BYTE TO THE NEXT. 



Figure 4.4 



We won't deal with a generalized multiplication routine here, but a couple 
of specific examples can be shown. 

How can we multiply by four? Multiply by two, twice. How can we multiply 
by eight? Multiply by two, three times. 

Here's an important one. We often want to multiply by ten. For example, 
if a decimal number is being typed in at the keyboard, the number will 
arrive one digit at a time. The user might type Ell, for example. The 
program must then input the two and put it away; when the one arrives, 
the two must be multiplied by ten, giving twenty, and the one added; when 
the seven is typed, the twenty-one must be multiplied by ten before the 
seven is added. Result: 517 in binary. But we must first know how to 
multiply by ten. 

To multiply by ten, you first multiply by two; then multiply by two again. 
At this point, we have the original number times four. Now, add the original 
number, giving the original number times fivd. Multiply by two one last 
time and you've got it. We'll see an example of this in Chapter 7. 

Right Shift and Rotate: Dividing by Two 

If we can multiply by two by shifting (and rotating) left, we can divide by 
two by moving the bits the other way. If we have a multibyte number, we 
must start at the high end. 

LSR (logical shift right) puts a zero into the left (high-order) bit, moves all 
the bits over to the right, and drops the leftover bit into the carry. ROR 
(rotate right) puts the carry bit into the left bit, moves everything right, and 



64 



MACHINE LANGUAGE FOR COMMODORE MACHINES 











T — I — r 



LSR 
—I— 



T — I — r 



J I I i_i L 




C FLAG 

IN AN LSR, ZERO MOVES INTO THE HIGH BIT, AND ALL 
BITS MOVE RIGHT ONE POSITION; THE LOWEST BIT 
BECOMES THE CARRY. 

ROR 

9 r 



T 1 1 1 — I 1 1 — I 



I I L 



J I I l_l 



c 

IN A ROR, THE CARRY MOVES INTO THE HIGH BIT AND 
ALL BITS MOVE RIGHT ONE POSITION; THE LOWEST 
BIT BECOMES THE NEW CARRY. 



LSR 



ROR 



C H- 



ROR 



C 



TO DIVIDE A THREE-BYTE NUMBER BY TWO, WE SHIFT 
THE HIGH-ORDER BYTE WITH LSR; THEN WE USE ROR 
TO ALLOW THE C FLAG TO "LINK" FROM BYTE TO 
BYTE. 



Figure 4.5 



drops the leftover bit into ttie carry once again. At the end of a right-shifting 
sequence, the final carry bit might be considered a rema/nc/er after dividing 
by two. 

Comments on Shift and Rotate 

As you might expect of arithmetic instructions, the shift and rotate instruc- 
tions normally operate in the A register. But there's an extra bonus: these 
instructions also can operate directly on memory. In other words, the 
computer can go to any address in memory and shift the bits at that address 
directly, without loading the data into a register. 

For this reason, you'll often see the instructions coded with the identity of 
the A register coded in the address part of the instruction. We would code 



NUMBERS, ARITHMETIC, AND SUBROUTINES 



65 



LSR A so as to distinguish from LSB $1E3A, where the contents of 
memory is being shifted. 

When a rotate or shift is performed directly on a memory location, the Z, 
N, and C flags are affected according to the contents of memory. Z will 
be set if the contents of the location ends up as zero; N if the high bit is 
set; and C performs its standard role of catching the leftover bit. 

Some programmers wonder about the terms logical and arithmetic, used 
as part of the definition. The distinction is related to the way that signed 
numbers are treated. "Logical" means that the sign of a number will prob- 
ably be lost if the number was intended to be signed. "Arithmetic" means 
that the sign will probably be preserved. It's purely a terminology question: 
the bits themselves move exactly as you would expect them to do. 

Subroutines 

We have written programs that are subroutines called by BASIC. We have 

written subroutine calls to built-in operations such as $FFD2 or $FFE<. 
Can we also write our own subroutine and arrange to call it? 

Of course we can. RTS (return from subroutine) does not mean "return 
to BASIC." It means "return to whoever called this routine." If BASIC 
called up the machine language routine, RTS takes you back to BASIC. 
If another machine language program called up the subroutine, RTS will 
return to the calling point. 

We wrote a useful subroutine in the last chapter. Its purpose was to accept 
only numeric keys, echo them to the screen, and convert the ASCII value 
to binary. Now we'll use this subroutine to build a more powerful program. 
Here it is. Be sure it's entered in your computer. 



A 


□ 33C 


JSR 


$FFE1 


A 


033F 


BEQ 


$□351 


A 


□ 341 


JSR 


$FFE4 


A 


D3AA 


CMP 


#$30 


A 


D3Ay 


BCC 


$^33C 


A 


D3A& 


CMP 


#$3A 


A 


□ 34A 


BCS 


$^33C 


A 


Q3AC 


JSR 


$FFD2 


A 


034F 


AND 


#$^F 


A 


0351 


RTS 





66 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



The Project 

Here is our mission: using tlie above subroutine, we wisli to build a simple 
addition program. Here's how we want it to work. The user will touch a 
numeric l<ey, say "3". Immediately, "3 + " will appear on the screen. 
Now the user will touch another key, say "A", and the program will 
complete the addition so that the screen shows " 3 + = 7 " . We will 
assume that the total is in the range to R so that we don't have to worry 
about printing a two-digit answer— don't try 5 + 5 or you'll get a wrong 
answer. 

0128 note: Remember to check Appendix E, Exercises for the Commo- 
dore 128, for the appropriate coding. 

Here we go. We must start our coding at address $0355 so as not to 
disturb our subroutine. We'll need to give SYS 350 to make this one go. 

A 0355 JSR $D33C 

We call our prewritten subroutine, which waits for a numeric key, echos 
it to the screen, and converts the value to binary in the A register. 

Our next action is to print the plus sign. We know how to do this, once 
we look up the ASCII code for this character. Appendix D tells us that it's 
$EB, so we'll need to LDft #$5B and JSR $FFD2. But wait a minute! 
Our binary value is in the A register, and we don't want to lose it. Let's 
store the value somewhere: 

A 0355 STA $03CD 

A □35a LDA #$EB 

A □35A JSR $FFD2 

A 0350 JSR $Q33C 

We picked $03 CO, since nobody seems to be using it, and put the binary 
number safely away there. Now we print the plus sign, and go back to 
ask for another digit. 

When the subroutine returns, it has a new binary value in the A register; 
the digit has been neatly printed on the screen behind the plus sign. Now 
we need to print the equal sign. But again, wait! We must put our binary 
value away first. 

We could place the value into memory — perhaps $03C1 would do — but 
there's another way. We don't seem to be using X or Y for anything at 



NUMBERS, ARITHMETIC, AND SUBROUTINES 



67 



the moment, so let's slip the value across into one or the other. We have 
four "transfer" commands that will move information between A and either 
index register: 



Like the load series of commands, these instructions mal<e a copy of the 
information. Thus, after TAX, whatever information was in fi is now also 
in X. Again like the load commands, the Z and N status flags are affected 
by the information transferred, it doesn't matter whether we use X or Y. 
Let's pick X: 

a DabD TAX 

A DBbl LDA#$3D 
A 03fc3 JSR $FFD2 

We have put our second value into X and printed the equal sign ($BD). 
Now we can bring the value back and do our addition. The next two 
instructions can come in any order: 

A DBtb TXA 
A 03fc7 CLC 
A OBbfl ADC $D3CD 

We have our total in the A register. It's almost ready to print, except for 
one thing: it's in binary. We want it in ASCII. 

Assuming the total is in the range to "=1, we can convert it directly to a 
single ASCII digit with an OR A operation. (If it's greater than nine, you're 
cheating and the answer won't make sense.) 

A Q3LB ORA #$3D 
A a3tD JSR $FFDE 

Are you basically a neat person? Then you'll want to print a RETURN to 
start a new line: 

A □370 LDA #$DD 
A 0372 JSR $FFD5 
A 0375 RTS 

Check it with a disassembly. If you disassemble starting with the subrou- 
tine, you'll need more than one screen full of instructions to see it all. No 
problem. When the cursor flashes at the bottom of the screen, press the 
letter D and RETURN and you'll see a continuation of the listing. 



TAX— Transfer A to X 



TRY— Transfer A to Y 
TY A— Transfer Y to A 



TXA— Transfer X to A 



68 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Back to BASIC. This time we do nof give SYS flEfl—tliat's the subroutine 
and we want the main routine, remember? 

Give the SYS flSO command. Tap a couple of numeric keys that total 
nine or less. Watch the results appear instantly on the screen. 

If you like, set up a BASIC loop and call the routine several times. 

Project for enthusiasts: You couldn't resist, could you? You had to type 
in two digits that totaled over 9 and got a silly result. OK, your project is 
to try to expand the above code to allow for two-digit results. It's not that 
hard, since the highest possible total is ■=! + R or Ifl; so if there are two 
digits, the first one must be the digit 1. You'll need to compare for the 
result over binary nine, and then arrange for printing the one and sub- 
tracting ten if necessary. Sounds like fun. 

Things You Have Learned 

— We may decide to use a number as a signed value; in this case, the high bit 
of the number will be □ if the number is positive and 1 if the number is 
negative. It's up to us. As far as the computer is concerned, it's just bits in 
either case. 

—When a number might have a value that won't fit into an eight-bit byte, we 
may use more than one byte to hold the value. We have already done this 
to hold addresses in two bytes: there's a high byte to hold the high part of 
the value and a iow byte to hold the low part. 

—We may add two numbers together using the ADC instruction with the a 
register; we should always clear the carry flag before starting an addition. 
The carry flag will take care of multibyte numbers for us, providing we re- 
member to start the addition at the low end. 

—We may subtract two numbers using the SBC instruction with the a register; 
we should always set the carry flag before starting a subtraction. The carry— 
which is sometimes called an inverted borrow— \n\\\ take care of multibyte 
numbers for us, providing we remember to start the subtraction at the low 
end. 

— For unsigned numbers, the carry should end up as it started (clear for addition, 
set for subtraction); otherwise we have overflow in the result. For signed 
numbers, the carry doesn't matter; the V flag will be set if we have overflow. 

—We may multiply a byte by two with the aSL (arithmetic shift left) instruction. 
If we have a multiple-byte number, we may carry the multiplication through 
to other bytes by using the ROL (rotate left) instruction, starting at the low 
byte of the number. 

— We may divide a byte by two with the LSE (logical shift right) instruction. If 
we have a multiple-byte number, we may carry the division through to other 



NUMBERS, ARITHMETIC, AND SUBROUTINES 



69 



bytes by using the ROR (rotate right) instruction, starting at the high byte of 
the number. 

—The shift and rotate instructions may be used on the contents of the A register 
or directly on memory. The N and Z flags are affected, and the C flag plays 
an important role in the shift/rotate action. 

—If we wish to multiply by a value other than two, we may need to do more 
work but we can get there. 

—As we might have expected, we may write subroutines in machine language 
and then call them from machine language. It's a good way to organize your 
code. 

Questions and Projects 

Write a program to subtract two single-digit numbers, similar to the one 
in the above exercise. You may continue to use the subroutine from the 
previous chapter. 

Write a program to input a single-digit number. If the number is less than 
five, double it and print the result. If the number is five or over, divide it 
by two (discarding any remainder) and print the result. Try to produce a 
neat output. 

Write a program to input a single-digit number. Print the word ODD or 
EVEN behind the number, depending on whether it is odd or even. Use 
the LSR instruction followed byaBCCorBCS test to check for odd or 
even. 

If you've been following the logic, you have developed quite a bit of ca- 
pability in machine language. You can input, you can output, and you can 
do quite a bit of arithmetic in between. 

By now, you should have developed skills with the machine language 
monitor and feel much more comfortable zipping in and out. These skills 
are not difficult, but they are important to the beginner. Without them, you 
can never get comfortably into the real meat: how to code machine lan- 
guage itself. 



5 



Address 
Modes 

This chapter discusses: 

• Non-addresses: implied, immediate, register 

• Absolute and zero-page 

• Indexing 

• The relative address for branches 

• Indirect addressing 

• Indirect, indexed 



71 



72 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Addressing Modes 

Computer instructions come in two parts: tlie instruction itself, or op code, 
and the address, or operand. Tfie term "address" is a little misleading, 
since sometimes the operand does not refer to any memory address. 

The term address mode refers to the way in which the instruction obtains 
information. Depending on how you count them, there are up to 13 ad- 
dress modes used by the 650x microprocessor. They may be summarized 
as follows: 

1. No memory address: Implied, accumulator. 

2. No address, but a value supplied: immediate. 

3. An address designating a single memory location: absolute; zero-page. 

4. An indexed address designating a range of S 5 fc locations: absolute,x; ab- 
solute,'^; zero-page,x; zero-page.y. 

5. A location in which the real (two-byte) jump address may be found: indirect. 

6. An offset value (e.g., fonward "R, back 17) used for branch Instructions: 
relative. 

7. Combination of indirect and indexed addresses, useful for reaching data 
anywhere in memory: indirect, indexed; indexed, indirect. 

No Address: Implied Mode 

Instructions such as INX (increment X), BRK (break), and TfiY (transfer 
a to Y) need no address; they make no memory reference and are com- 
plete in themselves. Such instructions occupy one byte of memory. 

We might say that such instructions have "no address." The precise term 
is "implied address," which seems to say that there is in fact an address 
but we do not need to state it. 

Perhaps the word "implied" is usecj in this manner: an instruction such as 
INX implies the use of the address register; and an instruction such as 
BRK implies the address of the machine language monitor. If so, there's 
an instruction that still defies this definition: NOP. 

The Do-Nothing Instruction: NOP 

NOP (no operation) is an instruction that does nothing. It affects no data 
registers or flags. When a NOP instruction is given, nothing happens and 
the processor continues to the next instruction. It seems inappropriate to 



ADDRESS MODES 



73 



me that we say that NOP has an implied address. It doesn't do anything; 
it doesn't have an address at all. On the other hand, I suppose that logicians 
might say, "Yes, but it does nothing to the X register." 

The NOP instruction, whose op code is lEA, is surprisingly useful. It's 
not simply that if you're a contract programmer getting paid by the byte 
you might be tempted to put a large number of NOP instructions into your 
program. NOP can serve two important program testing functions: taking 
out unwanted instructions, or leaving space for extra instructions. 

It's not as easy to change a machine language program as it is to change 
a BASIC program. As you have seen, the instructions are placed in specific 
locations, if we wish to eliminate an instruction, we must either move all 
the following instructions down or fill in the space with NOP instructions. 
If we move the instructions, we may need to correct some of the addresses. 

Examine the following code: 

□ 350 LDA#$DD 

D3SE STA $123< 

□ 355 ORfi $3ASy 

If we decide to eliminate the instruction at D355 (STfi $123^), we must 
remove all three bytes. So we place code $Ea in locations D352, 0353, 
and 035<. 

Suppose we are testing a moderately large program. Most programs will 
break into distinct "modules," each of which does a specific job. One 
module might clear a portion of memory to zero, another might do a 
calculation, and so on. When we are checking out this program, It might 
be wise to look at each module as it runs. 

In this case, we might deliberately code a BRK (break) command between 
each program module. The program will start to run, and then it will break 
to the machine language monitor. Within the monitor, we can examine 
memory to ensure that this module has done the job as we planned it. 
When we are satisfied, we can start the next module using the . G com- 
mand. In this way, we can have tight testing control over our program. 

That's all very well, but when we have finished testing our program and 
are satisfied that it runs correctly, we don't want the BRK instructions 
there. That's easy to fix. We replace the BRK codes ($□□) with NOP's 
($E&), and the program will run through to the end. 

If we are writing a program and suspect that we may need to insert one 
or two extra instructions within a certain area of the code, we can put a 



74 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



number of NOP instructions there. Tlie space will be available for use 
when we need it. 

No Address: Accumulator Mode 

We have observed that the shift and rotate instructions, aSL, ROL, 
LSE / and ROR, allow data manipulation in either the A register of directly 
in memory. When we want to use the A register, or accumulator, you 
should note this fact as you code your program. For example, you would 
write ftSL R or sometimes just ASL. 

Where accumulator mode addressing is used, it has the same character- 
istics as implied addressing: the whole instruction fits into one byte. 

Where the shift/rotate instruction refers to a memory location, an address 
will of course be needed. These address modes will be described later. 

Other than the shift and rotate instructions, there is one other set of in- 
structions that manipulates memory directly. You may recall INX, INY, 
DEX, and DEY increment or decrement an index register. 

INC (increment memory) adds one to any memory location. DEC (dec- 
rement memory) subtracts one from any memory location. Both instruc- 
tions affect the Z and N flags. 

When an instruction modifies memory, the address mode is neither Implied 
nor accumulator. Memory reference addressing will be discussed later. 

Not Quite an Address: Immediate Mode 

Coding such as LDR #$3-^ does not reference a memory address. In- 
stead, it designates a specific value (in this case, $3^). An instruction 
with Immediate addressing takes up two bytes: one for the op code and 
the second for the immediate value. 

We have used immediate addressing several times. It has a "natural" feel, 
and it's fast and convenient. There is one potential pitfall: immediate ad- 
dressing is so easy to use that it may be abused. Each time you code an 
immediate address, ask yourself, "Could this value ever change?" By 
writing a value into a program, rather than a variable, you may be freezing 
that value forever. 

An example: a program is written for a VIC-20, which has EE columns on 
the screen. At various places In the program, values are compared to EE 
(hex lb), and EE is added or subtracted to various screen addresses. In 



ADDRESS MODES 



75 



each case, immediate mode addressing is used to provide the value of 
EE. Some time later, the programmer decides to convert to the Com- 
modore 64, which has A D columns on the screen. The programmer must 
change each immediate mode reference from EE to (hex Efi). 

If the value EE had been stored in a memory location so as to be used 
as a variable, all this receding would not be needed. The moral is clear: 
excessive use of immediate mode can call for extra programming work at 
a later time. 

There are certain instructions for which immediate addressing is not pos- 
sible. For example, we can LDfi #$00, that is, bring in the actual value 
zero rather than the contents of an address, but we cannot ST A imme- 
diate — we must store the information somewhere in memory. 

A Single Address: Absolute Mode 

An instruction might specify any address within memory — from $0000 
to $FFFF— and handle information from that address. Giving the full 
address is called absolute addressing; if you like, you can deal with in- 
formation absolutely anywhere in memory. 



MEMORY 

Figure 5.1 Absolute Mode Specifies One Address Anywhere Witliin IMemory. 

We have used absolute addresses several times. When we exchanged 
the contents of memory locations $03fl0 and $D3fil, we named these 
addresses as we used them. When we stored a value from the keyboard, 
we named location $OBCD. We have also used absolute addresses for 
program control: subroutines at$FFDEand$033C were called up sim- 
ply by giving the address. 

The JSR (jump subroutine) instruction calls up a subroutine anywhere in 
memory by using absolute addressing. There is also a JMP (jump) in- 
struction, which can transfer program execution to any location in memory; 
it's similar to the BASIC GOTO statement. JMP can use absolute ad- 
dressing — it can go anywhere. 

There's a limitation to absolute addressing, however. Once you have writ- 
ten the instruction, you can go only to the address stated. You cannot 
reach a range of locations; only one. 

One-location addressing can be good for any of several jobs. On the PET/ 



76 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



CBM, we might want to switch between text and graphics modes by ma- 
nipulating address 5 R ^ t fl (hexadecimal E fl 4 C) . On the VIC-20, we might 
lil<e to set the volume level of the sound generator by placing a value into 
location BfcflTfl (hex nODE). On a Commodore 64, the screen's back- 
ground color can be changed by manipulating address SBEfll (hex DD21). 
In each case, it's one specific address that we want; absolute addressing 
will do the job for us. And we will also use absolute addressing to reference 
the various RAM locations that we have picked for our own program "var- 
iables." 

Zero-Page Mode 

A hexadecimal address such as $aBai is sixteen bits long and takes up 
two bytes of memory. We call the high byte (in this case, $03), the 
"memory page" of the address. We might say (but usually don't) that this 
address is in page 3 at position $fil. 

$□□ $FF $!□□ 



Figure 5.2 Zero-Page Mode Specifies A Single Address from $□□ to $FF. 

Addresses such as $QQAC and lODF? are in page zero; in fact, page 
zero consists of all addresses from $□□□□ to $DOFF. Page-zero lo- 
cations are very popular and quite busy. There's an address mode spe- 
cially designed to quickly get to these locations: zero-page addressing. 
We may think of it as a short address, and omit the first two digits. Instead 
of coding LDA $DO'^D,we may write LDA and the resulting code 
will occupy less space and run slightly faster. 

Zero-page locations are so popular that we'll have a hard time finding 
spare locations for our own programs. As a result, we tend to conserve 
zero-page Ipcations on Commodore machines. We'll need the few that 
are available for a special addressing mode, indirect, indexed, that will 
be discussed later. 

There are many locations in zero page that are useful to read. For example, 
the BASIC system variable ST, which is important in input/output handling, 
may be examined there (location $Rt. in PET/CBM, location $"=10 in VIC- 
20 and Commodore 64). If you need to know whether the user is holding 
down a key, there's an address in zero page that will tell you that (location 
$q7 in PET/CBM, $CB in VIC and 64, $DA in C128). 

Zero-page addressing, like absolute addressing, references one location 



ADDRESS MODES 



77 



only. It's good for a specific vaiue; but for a range of values we need 
something more. 



A Range of 5 5 b Addresses: Absolute, 
Indexed Mode 



Indexing has already been used in Chapter 2. We give an absolute ad- 
dress, and then indicate that the contents of X or Y should be added to 
this address to give an effective address. 



Figure 5.3 

Indexing is used only for data handling: it's available for such activities as 
load and store, but not for branch or jump. Many instructions give you a 
choice of X or Y as an index register; a few are limited specifically to X 
or Y. Instructions that compare or store X and Y (CPX, CPY, STX, and 
STY) do not have absolute, indexed addressing; neither does the BIT 
instruction. 

An instruction using absolute, indexed addressing can reach up to 25 b 
locations. Registers X and Y may hold values from □ to 255, so that the 
effective address may range from the address given to 555 locations 
higher. Indexing always increases the address; there is no such thing as 
a negative index when used with an absolute address. If the address given 
is above $FFDO, a high value in the index may cause the address to 
"wrap around" and generate an effective address In the region of $ □ □ □ ; 
othenwise, the effective address is never lower than the instruction ad- 
dress. 

We've seen the use of indexing. An instruction can reference a certain 
address, then, as the program loops or as the need for information changes, 
the same instruction can reference the contents of a different address. 
The maximum range of E5ti locations is an important limitation. 




^--^1ndex 

VALUE 



BASE 
ADDRESS 



78 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



The "reach" of an absolute, indexed instruction allows it to handle infor- 
mation in buffers (such as the input buffer, keyboard buffer, cassette buffer); 
tables (such as the active file table); and short messages (such as HELLO 
or error messages). It's not big enough, however, to reach all parts of 
screen memory, all parts of a BASIC program, or all of RAM. For that, 
we'll use indirect, indexed addressing, which will be described later. 

All of Zero Page: Zero-Page, Indexed 

Zero-page, indexed addressing seems at first glance to be similar to the 
absolute, indexed mode. The address given (this time in zero-page) has 
the contents of the selected index added to it. But there's a difference: in 
this case, the effective address can never leave zero page. 

This mode usually uses the X register; only two instructions, LDX and 
STX, use the Yregister for zero-page, indexed addressing. In either case, 
the index is added to the zero-page address; if the total goes beyond zero 
page, the address "wraps around." As an example, if an instruction is 
coded LDa $ED , X and the X register contains 5Q at the time of exe- 
cution, the effective address will be $□ 030. The total ($ED + $50 or 
$130) will be trimmed back into zero page. 



$00 


$FF 















BASE 
ADDRESS 



Figure 5.4 

Thus, any zero-page address can be indexed to reach any other place in 
zero page; the reach of EEb locations represents the whole of zero page. 
This creates a new possibility: with zero-page, indexed addressing, we 
can achieve negative indexing. For this address mode only, we can index 
in a downward direction by using index register values such as $FF for 
- 1, $FE for - E, and so on. 

On Commodore machines, zero page is fairly well occupied. There is 
limited opportunity to use zero-page, indexed addressing. 



ADDRESS MODES 



79 



Branching: Relative Address Mode 

We have written several branch instructions already; the assembler al- 
lowed us to enter the actual addresses to which we want to branch. The 
assembler translates it to a different form — the relative address. 




Figure 5.5 

Relative address means, "branch forward or backwards a certain number 
of bytes from this point." The relative address is one byte, making the 
whole instruction two bytes long. Its value is taken as a signed number. 

A branch instruction with a relative address of $05 would mean, "if the 
branch is taken, skip the next 5 bytes." A branch instruction with a relative 
address of $F7 would mean, "if the branch is taken, back up ^ bytes 
from where you would othenwise be." As a signed number, $F7 is equal 
to a value of -R. 

We can calculate a branch by performing hexadecimal subtraction; the 
"target" address is subtracted from the PC address. If we have a branch 
at $ □ 3 4 1 that should go to $ □ 3 3 C, we would work as follows: $ 3 3 C 
(the target) minus $03^3 (the location following the branch instruction) 
would give a result of or minus 7. This is tedious to do, and often 
results in mistakes; such mistakes in calculating a branch address are 
often fatal to the program run. We are much better off using an assembler 
to work out the arithmetic for us. 

The longest branches are: $ 7 F, or 157 locations ahead; and $flD, or 
IE a locations back. This poses no difficulties with short programs, such 
as the ones we are writing here. But in larger programs, the branch may 
not be able to reach far enough. The usual solution to this is to place a 
JMP (jump) instruction nearby, which is capable of going anywhere in 
memory; JMP uses absolute addressing. The appropriate branch instruc- 
tion will go to the JMP, which in turn will take the program to the desired 
location. 

Advocates of programming style make the following argument. All pro- 
grams should be written into neat small modules. Logic blocks should be 



80 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



broken into subroutines, and tlie subroutines into even smaller subrou- 
tines; this way, everything is neat and testable. If you should find a branch 
that won't reach, ask yourself whether it's time to break your program into 
smaller chunks before the logic gets too messy. By the liberal use of 
subroutines, you can arrange your code so that all branches are short and 
easily within reach. If you do break up the program structure, the branches 
will then always reach. It's up to you to choose your coding style, but you 
might give the question some thought. 

An interesting aspect of relative addressing is that code containing branches 
is easy to relocate. A piece of code containing a branch to six locations 
ahead will work perfectly if the whole code is moved to a different location. 
This is not true of jumps and subroutine calls, or any code using absolute 
addressing— if the location changes, the address must be changed. 

TheROm Link— Jumps in Indirect Mode 

We have mentioned the J MP instruction that will take the program to any 
specified address. JMP has another address mode: indirect addressing. 

Indirect addressing is signaled by the use of parentheses around the 
address. It works this way. An address is supplied, but It's not the one we 
will eventually use. We take this address, and at the location it specifies, 
we'll find the effective address, or the indirect address. The indirect ad- 
dress is two bytes long, of course, and is stored in the usual 650x manner 
of low byte first. 

An example will help to make things clear. Suppose that at address $D33C 
we have the instruction JMP ($153^^). The parentheses tell us that in- 
direct addressing is involved. The machine code is hex tC 3 A 12; as 
always, the address is "turned around." Now suppose that at addresses 
$1S34 and $1235 we have stored values $EA and $tfl. The jump 
instruction would behave as follows: it would go to $1234 and $1235, 
get the contents, and the program would transfer to address $fcflE<. 



INDIRECT 
ADDRESS 



Figure 5.6 



ADDRESS MODES 



81 



The JMP indirect has a somewhat specialized use. Normally, if we want 
to transfer control to some location, we just JMP there; no need for the 
indirect step. But there's one quite important case where indirect jumps 
serve an important function. 

Within ROM, there are a large amount of permanent instructions that the 
computer uses to perform its tasks. Since it's in ROM, we can never change 
this code. If the various programs were linked only by means of JMP and 
JSR statements, they could not be changed, and we would not be able 
to modify the behavior of the machine. 

Built into the ROM program, there are a series of carefully planned indirect 
jumps. Instead of the ROM leaping from one instruction directly to another, 
it jumps indirectly via an address stored in RAM. We can change the 
contents of RAM; and if we change the address stored in RAM, we can 
modify the behavior of the system. The best-known indirect address is 
that associated with the interrupt sequence: it's at $OD'=ID in PET/CBM 
and $D31< in VIC, 64, PLUS/4, and C128. 

You might not code many indirect jumps, but you'll be glad that they are 
there in ROM. 

Data From Anywhere: Indirect, Indexed 

The problems with indexed addressing have been noted: the reach of only 
E5L bytes limits the data capability of this method. 

Indirect addressing seems to offer a total solution. We can write an in- 
struction that points at an indirect address. Since we can change the 
indirect address at will, or add to or subtract from it, we can cause our 
instruction to deal with data anywhere in memory. 

In fact, we get a limitation and a bonus. First, the limitation: for indirect, 
Indexed instructions the indirect address must be in zero-page — two bytes, 
of course, organized low byte first, as always. Next, the bonus: after the 
indirect address is obtained, it will be indexed with the Y register to form 
the final effective address. 

Let's step our way through the mechanism and see how it works. Suppose 
I code LDA ($CD). Y with values $11 in address IDDCD and $B2 in 
address $0DC1. If the Y register contains a value of 3, the instruction 
will follow these steps: The address of $DDCD/1 is extracted, giving 
'$5211; then the contents of Y are added to give the effective address 
of If the contents of Y changed, the effective address would 



82 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



change slightly. If the indirect address at $CD and $C1 was changed, 
the effective address would change radically. 

The combination of indirect and indexing may seem lil<e overl<ill. If you 
can designate any location in memory with an indirect address, why bother 
with indexing? After ail, anywhere plus one is still anywhere. 

Indirect addressing plus indexing proves to be an ideal combination for 
the manipulation of data. Almost all data breaks up into logical chunks of 
some sort: records, table entries, screen lines, words, and so on. Here's 
the technique. We position the indirect address at the start of a given 
logical data chunk, and use the Y register to scan through the information. 
When we're ready to move to the next item, we move the indirect address 
along, and repeat the same scanning of the Y register through the new 
data. 



00 



FF 



INDIRECT, 
INDEXED" 



rv i I 



Figure 5.7 

One may think of it as a fishing analogy: We anchor the boat in a certain 
spot (fix the indirect address) and then use the fishing line (the Y register) 
to reach the data we need. When we're ready for the next item, we pull 
up the anchor and move along to a new place. 



■DATA IN MEMORY- 



NAME, ETC. 


NAME, ETC. 


NAME, ETC. 


A E 


3 





Figure 5.8 



We'll be working through an elaborate example that uses indirect, indexed 
addressing to manipulate the computer screen. First, a brief diversion. 



ADDRESS MODES 



83 



A Rarity: Indexed, Indirect 

There is another addressing mode that is little used in Commodore com- 
puters: indexed, indirect. It uses the X register rather than the Y, and is 
coded as in the following example: LDA ($CD , X). In this case, indexing 
takes place first. The contents of X are added to the indirect address (in 
this case, $CD) to mal<e an effective indirect address. If X were equal to 
A in this example, the effective indirect address would be SOQCA, and 
the contents of $OQCA and $DDC5 would be used as the effective 
address of the data. 



$00 



$FF 



1 




INDEXED, INDIRECT ALLOWS ONE OF SEVERAL 
INDIRECT ADDRESSES TO BE CHOSEN USING 
THE X INDEX REGISTER 



Figure 5.9 

In certain types of control processing, this is a quite useful address mode. 
X will contain an even number; since each indirect address is two bytes 
long, we will need to skip from one to the other, two bytes at a time. 

Let's take a hypothetical communications system that is connected to four 
telecommunications lines and see how indexed, indirect addressing might 
be used. Characters are being received from the four lines almost simul- 
taneously. As each character arrives, it must be put away into a memory 
buffer belonging to that particular line; in that way, traffic received from 
the various sources won't get mixed together. Zero-page will contain four 
indirect addresses, one for each line; each indirect address points at an 
input area for one line. Suppose a character is received into the A register 
from one of the lines; the line number (times two) is in the X register. We 



84 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



could then put the character away with the instruction STft ($tO,X). 
Thus, if line zero was involved, its indirect address at address $bQ/tl 
would be used; for line 1, the address at $bE/b3 would be used; and 
so on. After we had stored the character concerned, we'd need to bump 
the indirect pointer so that the next character will go into a new position: 
INC $tiD , X would do the trick. 

The above example is a rather specialized use of the indexed, indirect 
address mode. You may never need to use this mode. Indeed, most 
programmers lead full, rich lives without ever writing code that uses in- 
dexed, indirect addressing. 

The Great Zero-Page Hunt 

Indirect, indexed addresses are very important. They are your gateway to 
reaching any part of memory from a single instruction. But you must have 
two bytes available in zero-page for each indirect address you want to 
use. 

The Commodore ROM system helps itself to liberal amounts of zero-page 
memory. You don't have much empty space left over. How can you find 
space for these indirect pointers? 

First, look for unused locations. There are only a few of them: on the VIC 
and Commodore 64, you'll find four locations at locations $DOFCto$DDFF. 
That's enough for two indirect addresses. 

If you need more, look through the memory maps for locations designed 
as "work areas" or "utility pointers." They can usually be put to work for 
a temporary job. 

Finally, you can take working parts of zero-page and copy them to some 
other parts of memory. You can use these locations, carefully putting back 
the original contents before returning to BASIC. Don't try this with any 
values that are used by the interrupt routines (involved with screen, key- 
board, or RS-232); the interrupt can and does strike while your machine 
language program is running. And if the interrupt program changes these 
zero-page values, your program is going to behave badly. 

Project: Screen Manipulation 

This project is intended to show how indirect, indexed addressing can be 
used effectively. We'll change something on the screen — enough so that 
we reach more than 25 1 addresses. Ordinary indexing, therefore, won't 
do. 



ADDRESS MODES 



85 



We'll select a number of lines on the screen; within each line, we'll change 
a certain group of characters. In other words, we will write the code so as 
to manipulate a window on the screen. 

To do this, we'll need to code two steps: setting up the start of a screen 
line, and later moving on to the next line when needed. Within each line, 
we'll work our way through the range of screen columns that we have 
selected. In fact, it's a big loop (for the lines) containing a small loop (for 
the columns within that line). We'll use indirect addressing to point to the 
start of each line, and indexing (the Y register) to select the portion of that 
line to change. 

Since there's a variety of Commodore machines, we have some problems 
to resolve. Except for the C 128 in 80-column screen mode, all Commodore 
screens are "memory mapped," that is, the information appearing on the 
screen is copied directly from some part of memory. We may change the 
screen by changing the appropriate memory. But different machines use 
different memory addresses; and in VIC and Commodore 64, the screen 
may be moved around. Another thing to consider is that the length of line 
varies between different machines— it might be EE or 4 □ or flD columns. 

C128 note: Remember to checi< Appendix E, Exercises forttie Commo- 
dore 128, for the appropriate coding. 

No problem. If you have a 40-column machine, AQ equals $Efl; code 
A 0330 LDfl #$Efl 

For a 22-coiumn machine, change the above to LDA #$lt; and for an 
80-column PET, code LDfi #$5D. 

Have you coded the correct value? Let's proceed with our next decision. 
In the PET/CBM, screen memory starts at address IflDDO; in VIC or 
Commodore 64, the screen starts at whatever page is designated in ad- 
dress $DEflfl. Let's code as follows: 

PET/CBM: R 033E LDX #$flD 

A Q3AD NOP 
VIC/Commodore 64: aD33ELDX$DEafl 

The NOP instruction does nothing, but it makes the coding the same length 
so that we may continue with address $D3A1 in either case. The ft 
register tells us our line length, and the X register tells us the page number 
on which the screen starts. Let's put them away. The line length will be 



86 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



needed for addition later, so we may put it anywhere safe; the screen 
address will be part of an indirect address, so it must go into zero-page. 

It's hard to find a zero-page address that may be used in all Commodore 
machines; we'll choose $OQBB and $DOBC. $BB contains the low byte 
of the address, of course. Let's code 

a D3A1 STa $o3ao 

a U3AA STX $BC 

Note that we are using the zero-page addressing mode for the instruction 
at address $03^4. That puts the high byte of the address in place. Now 
we'll set the low byte to zero: 

a Q3Ah LDa #$□□ 
a U3A& STa $BB 

Our indirect address is now pointing at the start of screen memory. Let's 
discuss in more detail what we want to do with the screen. Specifically, 
we want to change a number of lines, let's say lA, on the screen. We 
will step along our indirect address by adding to the indirect address: 
maybe E2, maybe AU, maybe fiD; whatever is in address $D3aD. And 
we won't do the whole line; we'll start in column 5 and go to column Ifl. 
Let's count the lines in the X register; we'll start X at zero 

a Q3AA LDX #$0Q 

Now we're ready to do a screen line. Later, we'll adjust the indirect address 
and come back here to do another line. We should make a note to our- 
selves: "Come back to $ 0340 for the next screen line." 

The indirect address is pointing at the start of the line. We want to start 
work in column 5. That means that Y should start with an offset of A (the 
start of the line plus A). Let's do it: 

a03^CLDY#$D4 

We're going to walk Y up, and loop back to this point for the next character 
on the line. We might note: "Come back to $ 3 <E for the next character." 

We're ready to go. Let's dig out the character that's currently on the screen: 

a □34E LDa {$BB) ,Y 

This is worth a review. Locations $BB and $BC contain the address of 
the start of screen memory; on the PET/CBM, for example, this would be 
$ a □ □ 0. To this, we add the contents of Y (value A) to create an effective 
address of $flDD4; and from location $flQD^ we get the screen char- 
acter. 



ADDRESS MODES 



87 



We decide that we will leave spaces alone. The space character shows 
on the screen as a value of decimal 32, hex 20. Let's skip the next 
operation if it's a space: 

a D3SD CMP #$ED 
a Q3SE BEQ $035fc 

We have to guess at the address to which we will skip ahead, since we 
haven't gotten there yet. Make a note: "This address may need correction." 

a 035^ EOR #$flG 

This is where we manipulate the character. The EOR is a "flip-over" 
command; we're flipping the high bit of the screen value. You may look 
up screen codes to see what this does, or you may wait and see what 
happens. At this point, our code from $0352 joins up. As it happens, we 
were lucky again: the address is exactly right to rejoin at $035 1. But if 
it were not, you know how to fix it, don't you? Exit the assembler, then go 
back and type over. 

Now we put the modified character back to the screen: 

a D35t STa ($BB) ,y 

We have done one character. Let's move along the line to the next char- 
acter, and if we have passed column Ifl (Y = 17) we should quit and go 
to the next line. 

a D35fl INY 

a D35H CPY#$1E 

a 035B BCC $034E 

Y moves along to the next character position: five, then six the next time 
around, and so on. So Ibng as Y is less than Ifl (hex 12) we'll go back, 
since BCC means "branch less than." If we get past this point, we have 
completed the line and must move to the next one. 

We move to the next line by adding to the indirect address. We must add 
22, or ^0, or flO; the value is in address $Q3ao (you may remember 
that we stored it with the instruction at $0341). We must remember to 
clear the carry flag before starting the addition, and to add starting at the 
low byte of the address (at $BB). 



a D35D CLC 

a D35E LDA $BB 

a 03^0 aDC $D3ao 



88 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



A Q3L3 STA $BB 

A DBtS LDA $BC 

A DBt? ADC#$DD 

A DBtq STA $BC 

The last three instructions seem odd. Why would we add zero to the 
contents of $BC? Surely that changes nothing. The answer is obvious 
after a little thought: there might be a carry from the previous addition. 

Now we're ready to count the lines: we had decided to use X as a counter. 
Let's add one to X, and test to see whether we have done the lA lines: 

A 03tB INX 

A QBbC CPX #$nE 

A 03tE BNE $D3AC 

If we've done the required number of lines, we have nothing more to do 
other than return to BASIC: 

A DBTD RTS 

Disassemble and check It. Again, you'll find that the code occupies more 
than one full screen. Return to BASIC. 

This time, we'll write a small BASIC program to exercise the machine 
language code. Type NEW to clear out any old BASIC code, and enter 

lOD FOR J =1 to ID 
IID SYS flEfl 
lEU FOE K = 1 to 2DD 
13D NEXT K, J 

The extra loop is to slow things down. Machine language runs so fast that 
the effect might not be properly visible if run at full speed. 

Project for enthusiasts: Can you change the program to do a different 
set of columns? Could you change it so that it affected only the letter " S " 
wherever it appeared on the screen? 

Comment for VIC-20 and 
Commodore 64 

This exercise will work as intended. Other types of screen work might call 
for you to set the color nybble memory values before you can successfully 
work directly with screen memory. The rules for machine language are no 
different from those for BASIC: if you wish to POKE to the screen, you 
may need to take the color nybble area into account. 



ADDRESS MODES 



89 



Things You Have Learned 

—Three address modes are not addresses at all. Implied addressing means 
no address at all; accumulator addressing uses the A register and means 
the same thing; and immediate addressing uses a value, not an address. 

— Absolute addresses reference one location only, somewhere in memory. 
Zero-page addresses reference a single address in the range $ODOD to 
$□ OFF— the high byte of the address (□□) is the memory page. These 
address modes are used for fixed locations containing worl< values or system 
interfaces. 

—Absolute, indexed and zero-page, indexed allows the named address to be 
adjusted by the contents of an index register— X or Y. These instructions can 
reach a range of up to 55 1 addresses. They are commonly used for tables 
of data or temporary storage areas. 

—Relative addresses are used exclusively with branch instructions. They have 
a limited "reach" of about IE? locations fonward or backward. It takes a little 
arithmetic to calculate the proper values, but the computer usually works this 
out for us. 

—Indirect addressing is used only for jumps, most often to allow a fixed ROM 
program to take a variable jump. The average machine language programmer 
will seldom need these, but the principle of indirect addressing is worth learning. 

—Indirect, indexed addressing is the most important way to deal with data 
anywhere in memory. We may reach anywhere by setting the indirect address, 
then we may "fine adjust" that address by indexing it with the contents of Y. 

—Indirect, indexed addressing requires the indirect address to be in zero-page. 
We need to conserve zero-page locations for this use. 

— An addressing mode called indexed, indirect is rarely used when program- 
ming Commodore computers, but it's there if you want it. 

Questions and Projects 

Write a program to clear the screen of your computer— check Appendix 
C for the location of screen memory if you've forgotten. Don't just print 
the clear screen character ($R3); do it another way. Can you write the 
entire program without using indirect, indexed addressing? 

Write the program again using indirect, indexed addressing. The program 
may be a little shorter. Can you think of any other advantages of writing 
this way? 

A user wishes to type in a line of text on the keyboard, ending with a RE T U R N. 
He then wants to have the program repeat the line ten times on the screen. 
What addressing mode or modes would you use to handle the user's text? 
Why? You may try your hand at writing the program if you wish. 

Take one of the previous exercises and try to write it again without using 
immediate addressing. Is it hard to do? Can you see any reason to want 
to code without using immediate addressing at all? 



6 



Linking 
BASIC and 
Macliine 
Language 

This chapter discusses: 

• Where to put a machine language program 

• BASIC memory layout 

• Loading and the SO V pointer 

• BASIC variables: fixed, floating and string 

• Exchanging data with BASIC 



91 



92 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Siting the Program 

Up to this point, we liave been placing all programs in the cassette buffer. 
This is a good place for short test programs, but we need to examine 
alternatives that are often more attractive. 

BASIC Memory Layout 

C128 and B-128 note: These two machines keep variables in a separate 
memory bank from that in which the BASIC program is held. Some of the 
considerations described below— especially regarding dangers with the 
Start-of- Variables pointer— don't apply. For 0128 details, check Appendix 
E, under Exercises for the Commodore 128. 

BASIC RRM is organized according to the diagram below. The following 
locations are of particular interest: 

1 . Below the BASIC area, we have the cassette buffer area. This is available 
to us, providing we are not engaged in input/output activity. 

2. Start-of-BASIC (SOB) is usually a fixed address within the machine. In PET/ 
CBM, It's at lO^ai (decimal IDES). In Commodore 64, It's at SDflDl 
(decimal In the PLUS/4 series, It's at $10D1 (decimal AO^?). In 
the VlC-20, it may be at one of several places: $D^01, or $1ED1. 
A pointer marks this location. The pointer is located at $Sfl/$ER (decimal 
AQ and Al) in PET/CBIVI, and at $EB/$SC (decimal A3 and AA), In VIC- 
20, Commodore 64, and PLUS/4. 

You should inspect the pointer and confirm that It contains an appropriate 
address. You may notice that it's much easier to do this using the machine 
language monitor, since the address Is split between the two bytes (low order 
first, as always). 

3. End-of-BASIC Is signaled by three zero bytes somewhere after the SOB. If 
you command NEW in BASIC, you'll find the three bytes right at the start of 
BASIC; there Is no program, so start and end are together. There Is no 
pointer that Indicates end-of-BASIC, just the three zeros; but the next location 
(SOV) will often be directly behind the end-of-BASIC 



BASIC RAM 



f 










CASSETTE 
BUFFER 







BASIC 
PROGRAM 





BASIC 
VARIABLES 


BASIC 
ARRAYS 


FREE 


DYNAMIC 
STRINGS 





SOB SOV SOA EOA BOS TOM 

Figure 6.1 



LINKING BASIC AND MACHINE LANGUAGE 



93 



The BASIC program that you type in will occupy memory space from start- 
of-BASIC to end-of-BASIC. If you add lines to a program, end-of-BASIC will 
move up as extra memory IS taken up by your programs. If you delete lines, 
end-of-BASIC will move down. 

4. Start-of-variables (SO V) is often positioned directly behind the end-of-BASIC. 
When the BASIC program runs, the variables will be written into memory 
starting at this point; each variable is exactly seven bytes long. A pointer 
marks this location. The pointer is located at $EA/$EB (decimal <2 and 
A3) in PET/CBM, and at $ED/$aE (decimal AS and <t) in VIC-20, Com- 
modore 64, and PLUS/4. 

The SOV pointer is extremely important during BASIC load and save activ- 
ities. If we give the BASIC command SAVE in direct mode, the computer 
will automatically save all memory from SOB to just before the SOV. Thus, 
it saves the whole BASIC program, including the end-of-BASIC marker of 
three zero bytes, but does not save any variables. If we give the BASIC 
command LOAD in direct mode, the computer will automatically load the 
program, and thfen place the SOV pointer to just behind the last byte loaded. 
In this way, variables will never be stored over the BASIC program; they will 
be written above the end-of-BASIC. More on this later. 

If the BASIC program is changed, the SO V may move up or down as needed. 

5. Start-of-arrays (SO A) also represents one location beyond the end-of-BASIC 
variables, and thus could be named end-of-variables. Arrays created by the 
BASIC program, either by use of a D I M statement or by default dimensioning, 
will occupy memory starting at this point. A pointer marks this location. The 
pointer is located at $2C/$BD (decimal AA and -^5) in PET/CBM, and at 
$BF/$3D (decimal and A&) in VIC-20, Commodore 64, and PLUS/4. 
If the BASIC program is changed, the SOA pointer is set to match the SOV. 
Thus, all BASIC variables are wiped out the moment a change is made to 
the program. 

6. End-of-arrays (EOA) is set one location beyond the last array location in 
BASIC. Above this point is seemingly "free" memory — but it's not really free, 
as we'll see soon. A pointer marks this location. The pointer is located at 
$EE/$EF (decimal and A7) in PET/CBM, and at $31/$35 (decimal 
4 q and 50) in VIC-20, Commodore 64, and PLUS/4. 

If the BASIC program is changed, the EOA pointer is set to match the SOA 
and SOV . Thus, all BASIC arrays are wiped out the moment a change is 
made to the BASIC program. 

Let's change direction and start to work our way down from the top of BASIC 
memory. 

7. Top-of-memory (TOM ) is set one location beyond the last byte available to 
BASIC. On the PET/CBM and VIC-20, its location depends on the amount 
of memory fitted; a 32K PET would locate TOM at $flDDD. On the Com- 



94 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



modore 64, the TOM will normally be located at SAQDD. A pointer marks 
this location. The pointer is located at SB-^/SBS (decimal 52 and 
53) in PET/CBM, and at $37/$3fl (decimal 55 and 5E.) in VIC-20, Com- 
modore 64, and PLUS/4. 

If you examine the TOM pointer, you may find that it does not point at the 
expected position. That may be because of the machine language monitor, 
which has taken up residence at the top of memory and stolen away some 
memory. 

8. Bottom-of-strings, (BOS) is set to the last "dynamic" string that has been 
created. If there are no BASIC strings, the BOS will be set to the same 
address as TOM. As new dynamic strings are created, this pointer moves 
down from the top-of-memory towards the EOR address. A pointer marks 
this location. The pointer is located at $3D/$31 (decimal 4fl and 4R) in 
PET/CBM, and at $3 3/$ 34 (decimal 51 and 52) in VIC-20, Commodore 
64, and PLUS/4. 

A dynamic string is one that cannot be used directly from the program 
where it is defined; you might like to think of it as a manufactured string. 
If, within a BASIC program, I type: !□□ X$ = "HftPPY NEW YERR", 
the BASIC Interpreter will not need to store the string in upper memory; 
it will use the string directly from where it lies within the program. On the 
other hand, if I define strings with commands such as R$ = R$ + or 
INPUT N$, the strings must be built into some spare part of memory. 
That's where the BOS pointer comes in: the computed string is placed 
high In memory, and the BOS moved down to mark the next free place. 

If the BASIC program is changed, the BOS pointer is set to match the 
TOM. Thus, all strings are wiped out the moment a change is made to 
the BASIC program. 

Free Memory: The Dangerous Place 

It seems to beginners that there is a great deal of free memory available 
above the end-of-arrays and below the bottom-of-strings, and that this 
would be an ideal place to put a machine language program. This is a 
pitfall: it usually won't work. 

Here's the danger. As more and more dynamic strings are created, the 
bottom-of-strings location keeps moving down. Even when strings are no 
longer needed, they are abandoned and left dead in memory, taking up 
space. 

The BOS keeps moving down. Only when it touches the EOfi will the 
dead strings be cleaned up and the good ones repacked, an action called 
garbage collection. It's Important for BASIC programmers to know about 



LINKING BASIC AND MACHINE LANGUAGE 



95 



garbage collection: except on BASIC 4.0 and Commodore PLUS/4 sys- 
tems, it can be a cause of serious program slowdown. 

It's evident that the space between EOfi and BOS is not safe. If you put 
a program there, the strings will eventually destroy it. We must look else- 
where. 

Where to Put Your ML Program 

First, you may put your program in the cassette buffer. Providing you are 
not performing input/output activity, your program will be safe. Your space 
here is limited to IRQ characters or so. 



SOB sov SOA EOA BOS TOM 





CASSETTE 




BASIC ... 


VAR 


ARR 




STR 











Figure 6.2 

Second, move down the top-of-memory pointer and place the program in 
the space that has been freed. Your spdbe here is unlimited. Programs 
placed here will take up permanent residence until the power is turned 
off. Many monitors, such as Supermen, live here. 



SOB 



sov 



SOA 



EOA BOS 



NEW OLD 
TOMTOM 



C.B. 



Figure 6.3 



SOB 



OLD NEW SOA 
SOV SOV I 



EOA BOS TOM 




C.B. 



Figure 6.4 



Third, move up the start-of-variables pointer, and place the program after 
the end of BASIC and before the new start-of-variables. Your space here 



96 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



is unlimited. Programs placed here will tend to "join company" with the 
BASIC program; the two will save and load together. 

After moving a pointer— as was done in the last two methods — it's a good 
idea to return to BASIC and command CLR, so that all other variable 
pointers will align correctly with the ones that have moved. 

These three areas will be discussed more in a few moments. First, there 
are one or two extra locations available to VIC-20 and Commodore 64. 

Extras for VIC and Commodore 64 

The Commodore 64 has a free block of RAM at locations SCDOD to 
$CFFF (decimal ^RIBE to S3EA7). That's 4Kof RAM not being used; 
you may write your programs there. Before you do so, check to make sure 
that the memory is not being used by any other programs. It's a popular 
place in the Commodore 64, and many utilities and commercial programs 
zero in on this available memory. 

If you intend to write programs entirely in machine language, with no BASIC 
content at all, you may completely remove BASIC from the Commodore 
64 system and claim the space as available RAM. This gives you the 
whole block from $ fl □ 1 up to $ CFFF for programs and data — a whop- 
ping 50K— and even more could be liberated if necessary. BASIC may 
be made to disappear from the Commodore 64 with the equivalent of 
POKE IfSA (LDA #$3t, STA $□!). It may be reinstated with the 
equivalent of POKE 1 , 55 (LDA #$37 , STA$D1). Be very careful. 
With BASIC gone, the computer doesn't even know how to say READY. 

On all Commodore machines it's possible to move up the start-of-BASIC 
pointer and use the space freed below. To do so, it's essential to store a 
value of zero into the location immediately before the new start-of-BASIC, 
and to align all other pointers, usually by going to BASIC and commanding 
NEW. 

This works, and will make as much space available as is needed. BASIC 
programs will relocate as they load. But since the computer needs to be 
reconfigured before the main program is loaded, and often needs to be 
restored to its original configuration after the program is run, the method 
is not popular in most Commodore machines. It's used fairly often in the 
VIC-20, however. 

The video chip in the VIC-20 can "see" RAM memory only in the memory 
space $□□□□ to $1FFF (decimal to fllH). Whatever variable in- 
formation appears on the screen must be taken from this memory area. 



LINKING BASIC AND MACHINE LANGUAGE 



97 



The VIC-20 can also get information from $aDDD to SRFFF, but there's 
no RAM there; we can't manipulate this memory area. 

If we want to perform special visual effects on the VIC-20, we must ma- 
nipulate data in the area $Daaato$lFFF. Let's look at what is available. 
$DOOD to $D3FF is used by the "system;" other than the cassette 
buffer, we must leave it alone. $D^DD to $DFFF contains no memory 
unless a 3K BAM expansion is added. $!□□□ to $1DFF contains the 
BASIC program, and $ IE DO to $1FFF is screen memory. Details may 
vary, but the answer always comes out the same: there's no space to do 
our video effects. 

A popular VIC-20 solution, especially where 8K or more of RAM expansion 
has been added, is to increase the start-of-BASIC pointer, thus liberating 
space in low memory. This may now be used for visual effects and for 
machine language programming, too, if any space is left over. In the VIC- 
20, this approach is necessary, but it's still a bit clumsy. 



The start-of-variables pointer can be the cause of many troubles, if it's not 
understood. The rules covering it are as follows: 

1 . Variables are written starting at the SO V. 

2. BASIC S A VEs will save from memory beginning at start-of-BASIC and stop- 
ping at SOV. 

3. Direct command BASIC LOADs will bring a program into memory, relocating 
if appropriate, and then set the SO V pointer to the location following the last 
byte loaded. 

4. Changes to BASIC programs cause memory to be moved — up or down — 
starting from the point where the change Is mads and stopping at the SOV. 
The SOV will then be moved the appropriate distance up or down. 

These seem to be innocent rules. Rule 1 defines the purpose of the SOV. 
Rule 2 shows how the SOV controls the SAVE command so that the 
entire BASIC program is saved, but not the variables. Rule 3 arranges 
that short programs will have a large amount of variable space available; 
long ones will have less. Rule 4 ensures that a BASIC change makes 
extra room in memory or reclaims memory space. 

But if the SOV gets the wrong address, we're in trouble. The rules work 
against us. Variables may be written into disastrous places. SAVEs will 
cause too much or too little to be saved. LOADs may fix things, since 
SOV will be changed by the load action. An attempt to change a program 
with a bad SOV may cause too little or far too much memory to be moved 
around. We must get the SOV right. 




98 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



How can the SO V go bad on us? Let's take three examples, corresponding 
to the three major places that we might put machine language programs: 

We have a program in the cassette buffer, and a BASIC program that 
goes with it. We enter or load the BASIC program (the SOV is all right so 
far), and then we LOAD the machine language program; the SOV ends 
up disastrously somewhere in the cassette buffer area. 

We're in trouble. The program seems to list correctly, but it's sick. If we 
BUN, variables will start to be placed in the cassette buffer area; as more 
variables are created, they are placed in progressively higher memory 
locations. Eventually, the variables start to write over the BASIC program. 
Everything stops. The poor programmer says LIST to see what's hap- 
pened; his BASIC program is gone, and all that's left is gibberish. 

We're in more trouble. Alternatively, the programmer decides to save his 
BASIC program and commands SAVE. BASIC starts to save memory 
beginning at start-of-BASIC . . . and keeps saving, and saving, and saving. 
It won't stop until it reaches the SOV, but that's below where we started. 
We won't get there until the address "wraps around" and comes back up 
through zero. The poor programmer — if he or she waits long enough — 
discovers that the tiny five-line BASIC program has been saved as over 
E5D blocks on disk, or fifteen minutes worth of tape. And the saved 
program is useless. 

We're in still more trouble. Alternatively, the programmer lists the program, 
and decides to delete one character from a line of BASIC. BASIC im- 
mediately starts to move memory, starting at the change point. It won't 
stop moving memory until it reaches SOV, but that, again, is below where 
we started. It will move everything that can be moved. RftM will be moved 
along, which may not hurt anything; then the I A chips will be moved, 
which may scramble colors or make the display go crazy; then it will try 
to move ROM, which won't work because ROM can't be changed; then it 
will wrap around to zero-page and move everything there, which is fatal 
to the system. Eventually, it will collapse before reaching SOV since it 
destroys its own working pointers. 

All this could have been avoided if the programmer had loaded the machine 
language program first, and then loaded the BASIC program. The SOV 
would be placed behind the BASIC program, which is where it belongs in 
this case. 

Quiet Interlude 

It's easy to see how the problem occurs, once you understand about the 
SOV and its role. But if you don't understand the SOV, the results can 



UNKING BASIC AND MACHINE LANGUAGE 



99 



shake your self-confidence. Many programmers have given up on machine 
language because of a bad experience with SOV . 

It works this way. The student writes a perfect program into the cassette 
buffer and saves it using the machine language monitor. Later, with a 
BASIC program in place, the student recalls the program and inadvertently 
moves SOV to an impossible location. When BASIC runs, the variables 
will start to be written behind the machine language program, ahead of 
the BASIC program. As more and more variables come into play, they 
creep relentlessly toward the BASIC coding. 

Our eager student— with a perfect machine language program and a per- 
fect BASIC program— now decides to say RUN. The BASIC program runs 
for a while, and then grinds to a halt, usually with a crazy screen or reporting 
an error in a nonexistent line. We know what's happened, of course: the 
variables have started to write over the BASIC program. But our unfor- 
tunate student doesn't know that. The command LIST is entered, and 
out comes nonsense. 

What goes through the programmer's mind at this time? "I was so sure 
that the program is correct [in fact, it is]; but it's so bad that it's destroyed 
memory! I suppose that machine language is much more difficult than I 
thought." 

And the student loses hope and gives up, not knowing that there's only 
one small piece of information needed to fix everything up. This is only 
one of the things that might go wrong when the SOV pointer is improperly 
placed; even an attempt to change or save a BASIC program can cause 
system failure. 

Such experiences destroy confidence. They are responsible for the myth 
that machine language is hard and only super-clever programmers can 
cope with it. 

The Machine Language Monitor SAVE 

Now that we're becoming aware of the SOV pitfall, we're ready to discuss 
how to save a program in machine language. You probably understand 
why I've been delaying this command until this time. The MLM save com- 
mand typically goes 

S "PROGRAM", 01, DaacDati 

This would be the tape format. The command is S and is followed by 
the program name. The device is tape, so we type Dl — be sure to give 
two digits. Next comes the beginning address (in the example $D33C) 



100 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



followed by the end address plus one. In the example, the last location 
saved will be $D3tO. For disk saves, we might want to add the drive 
number: 

S "0:PROGRaM", Dfl, 0330, 03bl 

These programs, once saved, may be loaded directly from BASIC, but 
watch the SOV carefully. VIC-20 and Commodore 64 BASIC LORD com- 
mands should contain the extra field to defeat relocation: LORD "PRO- 
GRRM " , a / 1 will insist that the program load back into the same memory 
locations from which it was saved. 

More on LOAD 

There is a machine language L command to do a program load without 
changing any pointer (especially SOV). There are a number of different 
machine language monitors around, and the L command does not work 
the same way on all of them. You might check out the one you are using: 
ideally, the L command (format: L "PROGRfiM", Dl) should bring back 
the program without relocation. 

The L command is of limited value. A program user often cannot be 
expected to load up a machine language monitor and use it to go through 
a L load sequence. The program should take care of things for the user. 

We have been careful to say that the BASIC LORD command changes 
the SOV when given as a direct command. If a LORD command is given 
from within a program, SOV is not changed; but there's a new item to be 
taken care of. 

Programmed LORD has been carefully designed to perform a function 
called "chaining." That's a BASIC technique, and not within the scope of 
this book. Chaining, however, has two important characteristics: 

1 . No pointers are affected. The program will not lose any variables when it 
performs a LORD. That's good: we will not lose any of our computations. 

2. Once a LORD is complete, the BASIC program will resume execution at the 
first statemerit. It will not continue from where It left off; It will go back to the 
beginning. For our application, that's bad; we seem to have lost our place 
in BASIC. 

If we understand the problem that item 2 creates, we can easily fix it by 
using item 1. Here's an example to illustrate the problem: we have a 
program on disk written for the cassette buffer called " ML " , and we want 
to have a BASIC program bring it in. We could code as a first line: !□□ 
LORD " ML " , fi — but we'd have a problem. First, the program would load 



LINKING BASIC AND MACHINE LANGUAGE 



101 



ML. Then it would go back to the beginning and load ML. Then it would 
go back to the beginning . . . and so on. This is not satisfactory. Let's use 
rule 1 to fix everything: 

!□□ IF A = l GOTO 13D 

IID a = i 

150 LOAD "ML",fl,l 
13D . . . continues 

When we say RUN, the first line is executed, ft is not equal to one, so 
we continue on line IID . ft is set to one, and line lED causes a load 
of the desired program. BASIC goes back to the beginning, but all variables 
are preserved, so ft is still equal to 1. Line IDD tests ft and goes to line 
1 3D, the next statement beyond the load. Everything works as required. 
If there are multiple LOftDs, line lUD might be changed to ID □ ON ft 
GOTO 130, 15D,17D . . . as necessary. 

Caution: we are discussing the programmed LOfiD command only in the 
context of loading machine language modules. If you want to have a 
program load in another BASIC program (chaining or loading) the above 
rules still apply but may need to be used differently. 

Other SOY Blunders 

We have discussed the horrible results of loading a machine language 
program into the cassette buffer (using a direct command) after BASIC 
has been loaded. By now, we should have learned to avoid making this 
mistake. What about programs stored in other areas, such as high memory 
or after BASIC? 

Suppose we want to place a program into high memory, either by moving 
the top-of-memory pointer down to make room, or by using the spare RftM 
at $CDDD to $CFFF of the Commodore 64. We also have a BASIC 
program to load. Will loading in the wrong order harm SOV? 

The answer is yes, although the problem is not so severe. You can see 
that after loading a program to high memory using a direct command, 
SOV will be positioned immediately above it. But that's too high — there's 
no room for variables and we'll get an OUT OF MEMORY error for almost 
anything we do. 

Obviously, we can't leave SOV in the upper stratosphere. We must load 
the high memory first, and then the BASIC program. The second load will 
straighten out the SOV pointer. If you try this, you'll find that it is necessary 
to fix up the top-of-memory pointer and command NEW between the two 



102 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



loads; you cannot even give the next LORD command if you're apparently 
totally out of memory. 

Review: Fixing Pointers 

if in doubt, examine the pointers by displaying them with a M command. 
For VIC/64/PLUS/4, the command would be M QDEB QQ3A; with 
PET/CBIVI, use M DOSfl 0D37; in either case, be sure that the start- 
of-variables pointer is set to a "sound" value. 

As always, you can change an incorrect memory value — in this case, an 
incorrect vector— by moving the cursor back, typing over the values to be 
changed, and pressing RETURN. 

After End-of-BASIC— Harmony 

Suppose we place the machine language program behind the end-of- 
BASIC— that's the three zeros in memory— and move up the SOV so that 
variables won't disturb this program. How will everything work now? 

Things will work very well indeed. This time, we need to load our BASIC 
program first; the SOV will go immediately behind BASIC. Then we may 
load our machine language program, and the SOV moves right behind it. 
The SOV is in exactly the right place, assuming we load in the right order. 
(If we don't, the variables will destroy our machine language program.) 

Once our two programs are together, and we say S R VE , the combination 
program— BASIC and machine language together— will be saved. A little 
thought will reveal that memory from start-of-BASIC to just before start- 
of-variables contains everything we need. A subsequent load will bring 
everything back in, and position SOV to exactly the right place. We now 
have a "unit" program— BASIC and machine language working together, 
loading and saving as one program. 

There's one small problem in this arrangement. Once we have married 
the BASIC and machine language programs, we must not change the 
BASIC program. If we added to or subtracted from this program, the 
machine language program would move up or down — the relocation of 
memory goes right up to SOV. The program might not be able to work in 
the new place, and, of course, our SYS commands would be wrong. 

BASIC Variables 

There are four types of entry in the BASIC variable table. All variables, 
regardless of type, occupy seven bytes; the first two bytes are the name. 



LINKING BASIC AND MACHINE LANGUAGE 



103 



and the remaining five bytes (not always fully used) contain tlie value or 
definition. The variable type is signaled as part of the name: high bits are 
set over one or both letters of the name to signal a specific type. 



SOV 

L 



SOA 

L 



EACH VARIABLE IS EXACTLY 7 BYTES LONG. 
VARIABLES APPEAR IN THE ORDER IN 
WHICH THEY ARE USED. 

Figure 6.5 

For example, if a floating point variable had a name fiB, the name would 
be stored in the two bytes as $-^1 , $^E— the ASCII codes for fi and B. 
The same would be true if the variable were named ABACUS, since only 
the first two letters of the name are kept. In contrast, if the variable were 
named AB%, meaning that it was an integer variable, the name would be 
stored as $C1 , $C2. The ASCII codes are the same, but the high bit 
has been set over them. To complete the picture, a string variable named 
aB$ would be coded with the name $A1, $CE — the high bit is set over 
the second character only. 



r 



HIGH BIT SET FOR INTEGER VARIABLES AND FUNCTIONS 
HIGH BIT SET FOR INTEGER AND STRING VARIABLES 



NAME 


VALUE 


2 BYTES 
1 


5 BYTES 
1 1 1 1 



Figure 6.6 

There's a fourth type of entry that can go into the variable table, but it's 
not a variable: it's a function definition. If we give the variable command 
DEF FN A ( ... an entry will be made in this table. It will be distinguished 
by the high bit being set over the first character only. 

String variables use only three of the five bytes provided; the first byte 
signals the length of the string, and the next two bytes give the string's 
address. This group of three bytes is called a descriptor. 



704 MACHINE LANGUAGE FOR COMMODORE MACHINES 



There are two types of numeric variables: floating point and integer. Float- 
ing point variables use all five bytes; integer variables use the first two 
bytes only. It's possible to extract the value from a floating point variable 
and put it to work, but it's not a simple procedure. A description of how 
to do this is given in Appendix F. In contrast, it's quite easy to take the 
value from an integer variable and use it. 

Let's try an example. Type NEW, followed by A = 5 = : = 5. This cre- 
ates two different variables: ft and B%. Now go to the machine language 
monitor. The variables should be near the start-of-BASIC, but if you wish 
you can find their exact address by examining the SOV pointer ($2 a/ 
$2B on PET/CBM, or $ED/$EE on VIC, Commodore 64 or PLUS/4). On 
the Commodore 64, we might find that the variables start at $0flD3; to 
display both of them, we type M DflOB OfllD. We see the floating 
point variable, R: 

Al DO fl3 ED □□ OQ □□ 

The first two bytes are the name— $^1 is ASCII for ft, and the zero 
signifies no second letter— but Where's the 5? Embedded within the fl3 
ED □□ DO □□, that's where; and it's a good deal of work to extract the 
5 for further processing. 

Behind this variable, we see the integer variable, B: 

CE flD □□ ns □□ DO DD 

Hex CE is the ASCII for the letter B ( $^E ) with the high bit set. $flD is 
zero with the high bit set — again, there's no second letter. The value is 
in the next two bytes, and it's easy to read. The last three bytes are not 
used. 

Which is easier for machine language to interface with? Obviously, the 
integer variable. It's often quite suitable for the program work at hand: 
counting characters, setting pointers, and similar tasks. 

Exchanging Data: BASIC and Machine 
Language 

If BASIC and machine language wish to pass data back and forth, there 
are several approaches. Perhaps the simplest is to have BASIC POKE 
the values into a given location, and machine language load them as 
needed; in the opposite direction, machine language will store the values 
and BASIC will PEEK them. 

Another method is more sophisticated. BASIC variables are stored in 



LINKING BASIC AND MACHINE LANGUAGE 



105 



memory: why can't a machine language program go after the variables 
exactly where they lie and extract their value or change them? It sounds 
like a good idea. 

By now, we know how to ask machine language to search for a specific 
BASIC variable. Given the name, we can get the address of the first 
variable from the SOV pointer and store it as an indirect address. Using 
Indirect, indexed addressing and stepping the Y register from □ to 1 we 
can see if the name matches. If not, we add seven to the indirect address 
to take us to the next variable. If It does match, our indirect address is set 
up at the start of the variable; we can set Y to E , 3 , A , 5 , and t and 
extract the whole value. If the variable is type Integer, we need only extract 
the first two bytes (Y = 5 and 3). If the variable is not in the variable table, 
we'll step our Indirect address until It matches the start-of-arrays; at that 
point, we know that we have missed the variable. 

For a small number of variables, there's a short cut. Variables are placed 
into the variable table in the order in which they are defined: whichever 
variable Is defined first in the BASIC program will be first in the variable 
table. So if we arrange for our variables to be defined in a certain order, 
we can streamline our machine language search to "first variable," "sec- 
ond variable," and so on, with no need to examine the names. 

Let's take this one step further. If we want to use the first variable, all we 
need to have Is the address of the first variable somewhere in zero-page 
so that we may use It as an indirect address. We already have that ad- 
dress—it's the SOV, the start-of-variables, and it's there pointing helpfully 
at the first variable for us. By increasing the value of Y appropriately, we 
can reach beyond the first variable and Into the second or, for that matter, 
the third or the thirty-sixth. 

Project: We plan to place the machine language program behind the end- 
of-BASIC. This will vary, depending on the machine being used. The 
following code shows the correct addresses for the Commodore 64. Refer 
to Appendix E for other machines. 

CI 28 note: Remember to check Appendix E, under Exercises for the 
Commodore 128, for the appropriate coding. There's a lot here on how 
to dig out information from another memory bank. 

First, let's do our BASIC coding to estimate Its size. We need to guess at 
the location of the end-of-BASIC so as to place our machine language 
program. This program will ask machine language to take a value, V%, 
and multiply it by ten. Remember to say NEW. We write the BASIC program 
as follows: 



106 MACHINE LANGUAGE FOR COMMODORE MACHINES 



110 FOR J = l TO 5 

lED INPUT "VALUE" 

13D SYS + + + + 

140 PRINT "TIMES TEN = " ; 

150 NEXT J 

It seems likely that our BASIC program will occupy less than IE? bytes. 
We may check this later, but it seems safe to plan to start our machine 
language program at around EO-^R + lET.orElTt (hexadecimal fl fl 0). 
On that basis, we may change line 130 to SYS E 17 1. Do nof try to run 
the program yet. 

At this point, we could save the BASIC program to tape or disk and develop 
the machine language program. This would allow us to refine each of the 
two parts independently. For the sake of brevity — and because our ex- 
ample is an easy one and won't need touching up — we'll write the machine 
code directly into memory. 

Switch into the machine language monitor. Assemble the following code: 



A 


OfiflO 


LDY 


#$DE 




A 


OflflE 


LDA 


($ED) , 


Y 


A 


D&&A 


STA 


$033C 




A 


Oflfl? 


STA 


$033E 




A 


OflfiA 


LDY 


#$D3 




A 


OflflC 


LDA 


($ED), 


Y 


A 


OflflE 


STA 


$033D 




A 


Oflqi 


STA 


$033F 





We have now extracted two bytes from the first variable, V%. The high 
byte has been stored at both $033C and $033E; we'll see why in a 
moment. The low byte of the value has gone to $03 3D and $033F. 

Project for enthusiasts: You might be able to code the above more com- 
pactly by more effective use of indexing. 



A 




ASL 


$033D 


A 


oaq? 


ROL 


$033C 


A 


DflRA 


ASL 


$033D 


A 


oflqD 


ROL 


$D33C 



We have multiplied the contents of $D33D/$033C by two, and then we 
have multiplied it by two again. These locations now contain the original 
value times four. Note that we ASL the low byte and then ROL the high 



LINKING BASIC AND MACHINE LANGUAGE 



107 



byte. Perhaps we should be checking for overflow; but let's trust the num- 
ber to be within range for now. 

Since we have the original number times four in $ □ 3 3 D/$ 3 3 C, we can 
add it to the original number in $ 3 3 F/$ □ 3 3 E to get the original number 
times five: 



A 


OflAD 


CLC 




A 


□ flAl 


LDA 


$D33D 


A 


□ flA^ 


ADC 


$D33F 


A 


□ flA7 


STA 


$□330 


A 


□ AAA 


LDA 


$033C 


A 


OflAD 


ADC 


$D33E 


A 


□ flBD 


STA 


$D33C 



Now locations $D33C/$D33D contain the original number times five. If 
we double the number one last time, we'll have the value times ten: 

A 0&B3 ASL $033D 
A DflBt ROL $033C 

We have multiplied the number by ten. Now let's put it back into the var^ble 



A 


OflBq 


LDY 


#$0E 


A 


OflBB 


LDA 


$D33C 


A 


□ ABE 


STA 


($ED) ,Y 


A 


□ flCQ 


LDY 


#$□3 


A 


DflCS 


LDA 


$D33D 


A 


□ flC5 


STA 


($ED) ,Y 


A 


□ flC7 


RTS 



The numbers go back exactly the same way we drew them out. We must 
be careful to keep the high and low bytes correct. Integer variables have 
the high-order byte first, followed by the low-order byte; this is exactly the 
reverse of the way we use 650x addresses. 

We must perform one more task before wrapping up the program. We 
must change the start-of-variables pointer to a location above the machine 
language program. That would be SQflCfi, and so we display the SOV 
pointer with M UQEB □ DEE and change the pointer to 

:DD2D Cfl Dfl 

Check . . . disassemble . . . and then back to BASIC. List, and you'll 
see your BASIC program again. There's no sign of the machine language 
program, of course, but SAVE will now save everything together. 



708 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



RUN the BASIC program. Enter numbers as requested. Confirm that they 
are multiplied by ten. 

You may recall that our machine language program does not check for 
overflow. RUN the program again, and see if you can find the highest 
number that can be multiplied by ten without error. What happens at time 
of overflow? Is it what you expected? 

Project for enthusiasts: Can you add checks for overflow to the above 
program? You must decide what to do if overflow occurs: print a message; 
set the value to zero; or whatever you decide. But you shouldn't stop the 
program or break to the monitor. Such a thing would upset the program 
user. Your program will be longer. Don't forget, therefore, to change the 
SOV pointer at $ED/$EE so that your program is safe from variables 



—Small machine language programs can be conveniently written and checked 
out in the cassette buffer. We have been doing this during the exercises. This 
area Is not satisfactory for large programs, or programs we want to save on 
tape. 

—Programs can take up semi-permanent residence near the top-of-BASIC 
memory; the top-of-memory pointer needs to be moved down to protect it. 
These programs often need a separate "setup" to place them. 

—Programs can be placed behind the end-of-BASIC, which is marked by three 
consecutive zero bytes In memory. The start-of-varlables pointer must be 
Increased so that variables don't write over the program. Care must be taken 
not to change the BASIC program after this Is done. 

—The VIC-20 frequently has the start-of-BASIC moved up to make room for 
video information in lower memory. As long as we're moving this pointer, we 
might move It a little further and make room for some machine code. 

—The Commodore 64 has an unused block of RAM at addresses $CDDO to 
$CFFF; check to see that no other programs are using this area. 

—The start-of-variables pointer is intimately tied In with BASIC'S SAVE and 
LOAD commands. It Is extremely Important to ensure that any LOAD se- 
quence leaves this pointer in a safe place, so that variables cannot write over 
program code and thus cause program destruction. 

—Machine language monitor S (save) and L (load) commands can be used 
for staging programs in various parts of memory. Again, great care should 
be taken to ensure that the pointers are sound after the use of such instruc- 
tions. 

— A BASIC program may contain LOAD commands that will bring in any of the 
following: a different BASIC program, a machine language program, or data. 
Again, careful handling is needed. 




Learned 



LINKING BASIC AND MACHINE LANGUAGE 



709 



—BASIC variables are of three major types: integer, real (floating point), and 
string. I\^achine language programs are capable of reading and using any of 
them; in particular, integer variables are quite straightforward. 

—If we want, we can simplify the task of searching for BASIC variables by 
deliberately creating them in a certain sequence. 

Questions and Projects 

Write a simple BASIC and machine language program set that allows 
BASIC to input a number less than 25 1; POKE it somewhere in memory; 
call machine language that will divide the number by two; PEEK it back 
and print it. 

A program that brings in other programs is called a "boot," or, more 
accurately, a bootstrap program. Write a simple BASIC boot program to 
bring in a previous program exercise that was located in a cassette buffer 
(say, the program from Chapter 2 that printed HELLO), and then call it 
with a SYS. 

Bootstrap programs are especially popular with VIC, Commodore 64, and 
PLUS/4 for bringing in chunks of data such as sprites, new character sets, 
or whole display screens of information. You might like to try your hand 
at setting up such a system. 

Try your hand at this. I have a BASIC program that reads 

1D0X = 5 
110 SYS ... 
lEU PRINT A 

Write the machine language to be called by the SYS so that it changes 
the name of the variable X to A. Caution: this may be fun, but it's dangerous 
in real programs since you may end up with two variables that have the 
same name. 



This chapter discusses: 

• The stack for temporary storage 

• USE: an alternative to SYS 

• Interrupts: IRQ, NMI, and BRK 

• The la chips: PIA and VIA 

• Infiltrating BASIC: the wedge 



112 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



A Brief Intermission 

If you have been following along and performing the various projects, you 
should know a great deal about the principles of machine language. You 
should be capable of trying your hand at a number of small projects, and 
investigating areas that may be of special interest. 

This is a good time to stop and take stock. The remaining chapters are 
"icing on the cake" . . . they give extra detail and fine tuning on aspects 
of machine language. If you feel uncertain about any material covered so 
far, go back. Fix the fundamentals firmly in focus before you proceed and 
plunge into ponderous points of interest. 

Temporary Storage: Tlie Stacl< 

The stack is a convenient place to put temporary information. It works like 
a stack of documents: you may drop (or "push") an item onto the stack; 
when you take an item back again (or "pull"), you'll get the last one that 
you put there. Formally, it's called a last-in, first-out (LIFO) discipline; it's 
natural and easy to understand. 

The important rule to keep in mind about the stack is: "Leave these prem- 
ises as clean as when you found them." In other words, if you push three 
items onto the stack, be sure you pull those three items back off again. 
Don't ever branch away and leave the stack littered. 

The stack is in memory at page 1. The stack pointer (SP) is one of the 
items displayed in the register. To look for the information on the stack, 
you must add $ □ 1 □ □ to the value to get the next available stack position. 
As an example, if the SP shows a value of SFfl, the next item to go on 
the stack will go into address $01Ffl; the moment we put an item onto 
the stack, the pointer will move down so that it becomes $F7. 

As the stack is filled, the stack pointer goes down. As the items are brought 
back out of the stack, the stack pointer goes up. A low value in the stack 
pointer means a full stack: a value below $A0 signals trouble. 

The 650x chip itself doesn't give the stack any special treatment. If a 
machine language program— probably because of a coding error— wanted 
to push one thousand items onto the stack, that would be OK as far as 
the microprocessor was concerned. The stack would never leave page 1 : 
as the stack pointer went down beyond zero, it would wrap around to $FF 
and keep going. You'd never get those thousand distinct items back, of 
course. Similarly, if a program wanted to pull a thousand items from the 



STACK, USR, INTERRUPT, AND WEDGE 



113 



SP 



NEXT ITEM 
PUSHED WILL GO 
TO ADDRESS $01 F8 

NEXT ITEM 
PULLED WILL COME 
FROM ADDRESS $01 F9 

Figure 7.1 

stack— whether or not they had been put there before— the processor 
would happily move the stack pointer round and round page 1 , delivering 
bytes. There would only be B5t different values delivered, of course, but 
the processor doesn't care. 

Within the BASIC environment, the stack pointer starts around $FA (the 
first item will go into the stack at address $DlFfi), and goes down from 
there. When the stack pointer goes below about $<D, BASIC will signal 
OUT OF MEMORY. That's over lt.D available locations on the stack, 
plenty of room for most applications 

PHA (push A) and PLA (pull A) 

How may we use the stack? Suppose we have a value in the ft register 
and in a moment we will want to use it. First we need to print something, 
and the character to be printed must be loaded into the ft register. How 
can we put away the value in ft and bring it back later? We could slip it 
into another register with a transfer instruction (TAX or TRY) and bring 
it back from there; or, we could store it into memory and load it back. 
Alternatively, we could PUSH the ft register (PHft) to the stack and PULL 
(PL ft) the value back later. 

Again, let's do an example. Suppose the ft register contains 5, and the 



USED 


Olrr 


1 iccr\ 
UocU 


irc 


USED 


01 FD 


USED 


01 FC 


USED 


01FB 


USED 


01 FA 


USED 


01F9 


FREE 


01F8 



I I 

I I 
I I 



114 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



stack pointer is at $F 3. If \he program says P Ha, the value 5 is stored 
at address $D1F3, and the stacl< pointer changes to $F2. Later in the 
program, we encounter the instruction PLA: the stacl< pointer moves bacl< 
to $F3 and the value 5 is read from address $D1F3 and placed into 
the A register. 

It's a handy way to put away a value in a for a moment. 

PHP (push processor status) and PLP 

Sometimes when we are writing a program, we want to test for a condition 
now but act on the result of that test later. We can arrange to do this by 
putting the flags away for the time being, and then bringing them back 
when we want to test the flags. We use the instruction PHP (push the 
processor status word) to place all the flags on the stack, and PLP (pull 
the processor status word) to restore the flags to the status register (SR). 

Why would we need to do this? Perhaps an example will illustrate. Suppose 
we are reading a file of customer purchases, and as we input a data item, 
we discover that this is the last one— it's the end of the file. That means 
that we want to close the file and summarize the customer's activity — 
though not just yet. First, we must handle the item of information that we 
have input. So we can "stack" our end-of-file information, handle the last 
record in the same way as previous records, then bring back the status 
to see whether it's time to close the file and print the totals. We'll be using 
PHP and PLP for exactly this kind of task in the next chapter. 

PHA and PHP both put exactly one item onto the stack; PL a and PLP 
pull one item. There are other commands that handle more than one stack 
location. 

JSRanof RTS 

We know these commands. What are they doing here? 

When a JSR command is executed, the return address is placed onto 
the stack. When an RTS command is executed, the return address is 
picked from the stack, and that's where the program returns to. 

More precisely, when a JSR occurs, the processor places onto the stack 
the return address minus one as two bytes; the high-order part of the 
address goes to the stack first. When an RTS is encountered, the pro- 
cessor takes the two bytes from the stack, adds one, and then proceeds 
from the address so formed. 

Example: If address $0355 contains the command JSR $Q33C, the 



STACK, USR, INTERRUPT, AND WEDGE 



115 



following events occur. The return address would be $0355, the instruc- 
tion directly behind the JSR; but an address of $035^ is calculated — 
the 03 goes to the stack first, and the SA below it. The subroutine at 
$D33C now starts to run. Eventually, it encounters an RTS. The values 
SA and 03 are pulled from the stack and formed into address $Q3SA; 
one is added, and the processor resumes execution at address $Q355. 

You hardly need to know this. We have been using subroutines for some 
time without knowing that all this happened. But sometimes, it's useful to 
be able to examine the stack, asking, "Who called this subroutine?" The 
answer Is there. 

Interrupts and RTI 

There are three types of interrupt: IRQ, NMI, and the BRK instruction. 
IRQ (interrupt request) and NMI (non-maskable interrupt) are pins on 
the 650x. A suitable signal applied to the appropriate pin will cause the 
processor to stop what it's doing and run an interrupt routine. The BRK 
instruction might be thought of as a fake interrupt— it behaves in a similar 
manner to IRQ. 

When an interrupt signal occurs, the processor completes the instruction 
it is currently working on. Then it takes the PC (the program counter, which 
contains the address of the next instruction) and pushes it onto the stack, 
high byte first. Finally, it pushes the status register to the stack. That's a 
total of three bytes that go to the stack. 

The processor then takes its execution address from one of the following 
locations: 

IRQ or BRK— from $FFFE and $FFFF 
NMI —from $FFFR and $FFFB 

Whatever value is found in these pointers becomes the Interrupt execution 
address: the processor starts to run at this address. Eventually, the pro- 
cessor encounters an RTI instruction. The status register and the PC 
address are taken from the stack, and the interrupted program resumes 
where it left off. 

Note that the address on the stack is the return address. This differs from 
JSR/RTS, where the return address minus one is stored. 

On all Commodore machines, the IRQ strikes about sixty times a second. 
The NMI is unused (but available) on PET/CBM; it isn't available in the 



116 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Plus-4 series; and on VIC-20, Commodore 64, and Commodore 128, it is 
used for tlie RESTORE l<ey and for RS-232 communications. 

The BRK command can be distinguislied from tfie IRQ signai by means 
of a bit in tlie status register. Bit A is the B, or breal< flag; if it's set, the 
iast interrupt was caused by a BRK and not by an IRQ. 

Later, we wili discuss using the interrupt routines for our own programming. 
By the time we can "catch" the interrupt, several more things will have 
been pushed to the stacl<: the a, X, and Y registers. This is done by a 
ROM program, not the processor; but it will prove handy since we can use 
these registers, safe in the l<nowledge that they will be restored at the end 
of the interrupt. 

Mixing and Matcliing 

The processor uses the stack mechanically. If we know how to manipulate 
the stacl<, we can use it for surprising things. For example, an RTS can 
be given even though there was no subroutine call; all we have to do is 
prepare the stack with the proper address. Try to figure out what the 
following code will do: 

LDft 
PHA 

LDfi #$tfl 

PHft 

RTS 

This coding is identical to JMP We have placed a "false return 

address" onto the stack, and RTS has removed it and used it. This may 
not seem very useful, since we could easily have coded the JMP $B<tH 
directly. But look at the following code: 

LDa TABLEl, X 
PHa 

LDA TaBLEB, X 

PHa 

RTS 

The principle of coding is the same, but now we can "fan out" to any of 
several different addresses, depending on the value contained in X. 

USR: A Brother to SYS 

We have used SYS a number of times. It means, "Go to the address 
supplied and execute machine code there as a subroutine." U S R is similar 



STACK, USR, INTERRUPT, AND WEDGE 



117 



in many respects: it means, "Go to a fixed address and execute machine 
code there as a subroutine." The fixed address may be POKEd into the 
USR vector. On most Commodore machines this is at addresses 1 and 
E; on the Commodore 64, it's at addresses 7fl5 and 7 fit (hex OB 11 
and D315). 

There's another difference that seems important at first. SYS is a com- 
mand; USR is a function. You cannot type the command USR ( □ ) — ail 
you'ii get is SYNTAX ERROR. You must say something iil<e PRINT 
USR ( ) or X = USR ( D ) , where USR is used as a function. It seems 
as if SYS was meant to connect to action programs, and USR was meant 
to link to evaluation programs. In reality, the difference in usage is not that 
great. 

Whatever value is within the parentheses— the argument of the US R func- 
tion — is computed and placed into the floating accumulator before the 
USR function is called. The floating accumulator is located at $5E to $b3 
in most PET/CBM computers, and at $tl to $tt in VIC-20, Commodore 
64, and PLUS/4. Floating-point representation is complex, as we have 
hinted in Chapter 6. l\/lost beginning programmers prefer to leave this area 
alone and pass values through memory POKEs or integer variables. 

When the USR function returns control to BASIC, the function value will 
be whatever is in the floating accumulator. If we have not modified it, this 
will be the same as the argument, so that in many cases PRINT USR(5) 
would print a value of 5. 

Interrupts: NMI, IRQ, and BRK 

We have mentioned the mechanical aspects of interrupt. Now let's look 
at how to use the interrupt for simple jobs. 

The IRQ connects through a vector in RAM; if we change the address 
within the vector, we will change the address to which the interrupt goes. 
The interrupt vector is located as follows: 

Most PET/CBM: □□qD-ODRl (decimal lAA-lAS) 

VIC/Commodore 64:D314-0315 (decimal 7flfl-7flq) 

Before we change this vector, we should realize something quite important: 
the interrupt does a lot of work sixty times a second. It updates the clock, 
checks the RUN/STOP key, gives sen/ice to the cassette motors, flashes 
the cursor, and handles keyboard input. If you thoughtlessly change the 
IRQ vector, it will stop doing these things; and it's hard to handle a 



118 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



computer when it has a dead keyboard. You could try to program all these 
functions yourself; but there's an easier way. 

Suppose we use the vector to temporarily divert to our own program, and 
at the end of our program we allow the interrupt to continue with whatever 
it was going to do anyway. That way, our program would get service sixty 
times a second, and the usually interrupted jobs would still get done. 

It's not hard to do, and we can achieve many interesting effects by diverting 
the interrupt. Remember that the interrupt runs all the time, even when 
no BASIC program is running. By playing with the interrupt, we can make 
a permanent computer system change that is in effect even when no 
programs are in place. 

Care must be taken in changing an interrupt vector. Suppose we are 
beginning to change the two-byte address; we have changed the first byte, 
and suddenly, the interrupt strikes. It will use an address that's neither 
fish nor fowl: half is the old address, and half is the new. In such a case, 
it's likely that the interrupt will become confused; and if the interrupt Is 
confused, the whole computer is in trouble. We must find a way to prevent 
interrupt from striking when we change the vector. 

We could do this in machine language: before a routine to change the 
IRQ vector, we could give the instruction SE I (set interrupt disable). After 
this instruction is given, the IRQ cannot interrupt us. We may set the 
vector and then re-enable the interrupt with the instruction CLI (clear 
interrupt disable). Be sure that you do this, since the interrupt routine 
performs many vital functions. We may say that we have masked off the 
interrupt in the time period between execution of SEI and CLI. The NMI 
interrupt, however, is non-maskable, and SEI will have no effect on it. 

There's a second way of turning off the interrupt— that is, by shutting off 
the interrupt source. Something makes an interrupt happen— it might be 
a timer, it might be an external signal, or it might even be a screen event. 
Whatever it is, we can get to the source of the interrupt and disconnect 
it. 

Almost all interrupt signals are delivered through an I R (interface adaptor) 
chip; and these chips invariably allow the path of the interrupt signal to 
be blocked temporarily. We'll discuss the I A chips later; for the moment, 
the normal interrupt signals can be blocked with the following actions: 

Commodore 64: Store $7F into address IDCDD (POKE 5t333, 127) 
to disable; store $fll into the same address (POKE 5t333 ,lEq) to 
re-enable. 



STACK, USR, INTERRUPT, AND WEDGE 



119 



VIC-20: Store $7F into address $R1EE (POKE 371bb, 127) to dis- 
able; store $C0 into the same address (POKE 371bt,l'=IE) to re- 
enable. 

PET/CBM: Store $3C into address $Efll3 (POKE SR-^ll, tD) to dis- 
able; store $3D intothe same address (POKE 5'=i^ll,bl)to re-enable. 

It goes without saying that the above POKEs should not normally be given 
as direct commands; the first POKE in each case will disable the keyboard 
(among other things), and you won't be able to type the restoring POKE. 

A warning about interrupt programs: changing the IRQ vector is likely to 
make it difficult to load and save programs. You may need to put the vector 
back to its original state before you attempt any of these activities. 

An Interrupt Project 

The following project is written for the Commodore 64 only. The equivalent 
coding for PET/CBM and VIC-20 may be found in Appendix E. Appendix 
E, under Exercises for the Commodore 128, also contains appropriate 
coding for the C128. 

Let's write the coding for the interrupt itself. Sixty times a second, we'd 
like to copy the contents of address $H1 to the top of the screen. Here 
goes: 

a 0330 LDR $qi 
ft □33E STft $DADD 
ft □3<1 JMP ($D3ftD) 

Why the indirect jump? We want to "pick up" the regular interrupt routine, 
but we don't know where it is yet. When we find the address, we'll put it 
into locations $D3fta/$D3ftl so that the indirect jump will link things up 
for us. 

Now let's write the routine to enable the above interrupt coding. First, let's 
copy the interrupt address from $ □ 3 1 ^ into the indirect address at $ □ 3 ft □ : 

ft niAA LDft $Q31A 

ft niAl STft $Q3ftD 

ft 034ft LDft $0315 

ft U3AJ) STft $D3ftl 

Now we are ready to put the address of our own interrupt routine (at 
$□330) into the IRQ vector: 

A 0350 SEI 



120 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



A 


□ 351 


LDA 


#$3C 


A 


□ 353 


STA 


$U31A 


A 


□ 35b 


LDA 


#$□3 


A 


□ 35fl 


STA 


$□315 


A 


□ 35B 


CLI 




A 


□ 35C 


RTS 





We will enable the new interrupt procedure byaSYSto$D34<, above 
(SYS a 3b). Before we give that command, let's write the coding to put 
everything baci<: 



A 


□ 35D 


SEI 




A 


□ 35E 


LDA 


$^3A^ 


A 


□ 3bl 


STA 


$□314 


A 


Q3hA 


LDA 


$D3A1 


A 


□ 3fc7 


STA 


$□315 


A 


□ 3bA 


CLI 




A 


□ 3bB 


RTS 





As you can see, we put the original address back, copying it from the 
indirect address area where it was saved. 

Once this code is in place, disassembled, and checked, you may return 
to BASIC. SYS fl3t. will invoke the new interrupt code; SYS flfcl will 
turn it off. Note that the character (a copy of the contents of address $"=11) 
appears at the top left of the screen. The character seems to be affected 
by pressing some keys; can you establish how many keys are involved? 

Some models of Commodore 64 may print blue-on-blue when screen 
memory is POKEd, as we are doing now. If so, the character may not 
always appear in the left-hand corner. Project for enthusiasts: Fix this 
problem by storing a value into the color nybble table at address $Dfl □□. 

The I A Chips: P I A, VIA, and CIA 

The interface adaptor (I A) chips are richly detailed. To understand them 
fully, you'll need to read the specifications in some detail. Here, we'll give 
their main functions. 

PI A stands for peripheral interface adaptor, VIA for versatile interface 
adaptor, and CIA for complex interface adaptor. There is speculation 
among Commodore owners that the next interface chip will be called "FBI." 

The functions performed by an interface adaptor are: 



STACK, USR, INTERRUPT, AND WEDGE 



121 



1 . Event latching and interrupt control. We have noted that these chips can be 
manipulated to block the interrupt signal. In fact, they do more than "gating" 
the signal — allowing it through to the processor's IRQ trigger or alternatively 
blocking it. They also often latch a signal into an event flag, sometimes called 
an interrupt flag. 

Latching is important. A triggering event may be brief; so short, in fact, that 
the original signal causing interrupt might go away before the processor can 
look at it. An Ifl event flag locks in the signal and holds it until the program 
turns it off. 



ON 



INTERRUPTING - 
EVENT 



Figure 7.2 



LATCH 



EVENT 
FLAG 



OFF 



COMPUTER 
ACKNOWLEDGEMENT 



If an event has time importance— that is, if the event's timing must be ac- 
curately measured, or if the event flag must be cleared quickly so as to allow 
for the detection of a new event— we may link the event flag to the interrupt 
line. If we do so, the occurrence of the event will cause the processor to be 
interrupted. We must write coding linked to the interrupt routines to detect 
this event, clear the flag, and do whatever processing is needed. We set up 
this link to the interrupt line by means of a register usually called the interrupt 
enable register. 

On the other hand, the event might not be particularly time critical. In this 
case, you can simply check the appropriate event flag from time to lime. 
When the event occurs, you may then clear the flag and handle it. No interrupt 
is needed. Even when an event flag is not connected to the interrupt, it may 
be called an interrupt flag; don't let the terminology confuse you. 

Whether or not you handle these events through interrupt sequences, it's 
important to know that It's your job to turn the event flag off. The flag will 
hold the signal until it's turned off— and it usually won't turn off unless your 
program takes some action to do this. 

The various flags are triggered by timers or external signals. You can read 
a flag's state by checking the interrupt flag register. Several flags will be 
packed together in this register; as always, you will use the logical operators— 
AND, OR A, or EOE— to extract or modify the particular flags in which you 
are interested. You may also use the IFR (interrupt flag register) to clear 
the flags. 



722 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



2. Timing. Certain addresses witfiin thie I A cliip are often assigned as "timers." 
Ttiese timers count down; in othier words, if we place a value of $R? into a 
timer and lool< at the value immediately, we might find that it has gone down 
to $"^3. Timers come in many shapes and sizes— again, checl< the chip 
reference for details— but most of them toggle an interrupt flag when they 
have counted down to zero. As discussed, you may choose whether or not 
this flag will really cause an interrupt signal. 

3. Input/output. Certain addresses within the I a chip are connected to "ports," 
which extend outside the computer. Thus, the computer can detect external 
events or control external devices. Output signals are usually latching in 
nature: in other words, a store command might be taken to mean, "tum on 
port 5 and leave it on." 

Tips on lA Chips 

Many addresses within an I A chip have a different meaning, depending 
on whether they are being written to (stored) or read (loaded). Watch for 
this when you are reading the chip specifications. 

Often, the action required to turn an interrupt flag off is odd. It !ool<s like 
the kind of thing you should do to turn the flag on. Keep in mind that a 
flag may be turned on only by the external activity to which it is linked. 
So, although it may seem odd to turn the flag in bit zero off by storing a 
value of 1 (which would seem to want to turn bit zero on), don't worry. 
You'll get used to it. 

The lER (interrupt enable register) is often a source of problems. In many 
cases, the high bit of a value we are storing has a special meaning: if it's 
set, the other bits will cause the appropriate interrupt connections to turn 
on; if it's clear, the other bits will cause the appropriate interrupt connec- 
tions to be turned off. You may recall that we shut off the Commodore 64 
interrupt by storing $7F into address $DCOD. This may seem odd: we're 
storing a binary value of$Dlllllll, which might seem to be turning 
bits on. In fact, the high bit of zero signals that all the remaining bits 
are"turn off" signals; so the value causes all interrupts to be blocked. 

Infiltrating BASIC: The Wedge 

In zero-page, there's a subroutine that the BASIC interpreter uses fre- 
quently to obtain information from your BASIC program. It's used to get 
a character from your BASIC program, and to check it for type (numeric, 
end-of-command, or other). 

The routine is normally entered at either of two points: CHEGET, to get 



STACK. USR. INTERRUPT, AND WEDGE 



123 



the next character from your BASIC program; and CHRGOT, to recheck 
the last character. The subroutine is located at$DD7nto$DDfl7ln most 
PET/CBM computers, and at $ □ □? 3 to $ □ □ fl A in VIC-20 or Commodore 
64. You may disassemble it there if you wish. The coding is described 
below. 

Since CHRGET is in different locations, depending on the machine, the 
following coding is shown with symbolic addresses. That is, instead of 
showing the hex address value, the address is given a name, or symbol. 
Thus, CHRGOT might represent address $DD7q, CHRGOT + 1 would 
represent address $□□?&, and so on. 

CHRGET INCCHRGOT + 1 

BNE CHRGOT 

INC CHRGOT + 2 
CHRGOT LDA xxxx 

This subroutine is self-modifying, that is, it changes part of itself as it runs. 
That's not always a good programming technique, but it works well here. 

The first part of the subroutine adds one to the address used by instruction 
CHRGOT. This is a standard way of coding an address increment: add 
one to the low byte of the address; if that makes it zero, the low byte must 
have gone from $FF to $D0, in which case, add one to the high byte. 

The address loaded by CHRGOT is within your BASIC program, or within 
the input buffer if you have just typed a direct command. Before we follow 
the next piece of code, let's look at our objectives: 

1. If we find a space, go back and get the next character. 

2. If we find a zero (BASIC end of line) or a colon (hex $3 A, BASIC end-of- 
statement), we wish to set the Z flag and exit. 

3. If we find a numeric, we wish the C flag to be clear; if we do not find a 
numeric, we wish the C flag to be set. 

CHRGOT LDA XXXX 
CMP #$3A 
BCS EXIT 

If the character is a colon ($3 A), we'll leave the subroutine with the Z 
flag set. That's one of our objectives. Here's part of another one: if the 
character is $3 A or higher, it can't possibly be an ASCII numeric — 
numerics are in the range of $3D to $3^. 

CMP #$2D 
BEQ CHRGET 



124 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



If the character is a space, we go back and get another character. 

The following coding looks rather strange, but it's correct. After the two 
subtractions, the a register will be back where it started: 

SEC 

SBC#$3D 
SEC 

SBC #$DD 

After this, the R register is not changed; but the C flag will be set if the 
number is less than $30, which means that it is not an ASCII numeric. 
Additionally, the Z flag will bet set if a contains a binary zero. We have 
met all our objectives and may now return: 

EXIT RTS 

Breaking Into BASIC 

Since BASIC comes to this subroutine often, we can infiltrate BASIC by 
changing this subroutine. Extra coding in this area is often called a "wedge" 
program. We must be very careful: 

• We must leave a, X, and Y unchanged; either we must not use them or we 
must save them away and bring them back. 

• We must not interfere with the flags. 

• We must be careful not to slow BASIC down too much. 

This is a tall order. The last requirement is often helped by two techniques: 
use the wedge to implement extra commands in direct mode only; and 
make use of a special character to identify our special commands. 

In PET/CBM, we may choose to modify this subroutine in either of two 
places: near the beginning, in CHRGET; or after the LDa, in CHRGOT. 
Each location has its advantages. In the CHRGET area, we don't need 
to preserve the a register or status flags, since CHRGOT will fix them up 
for us. In the area following CHRGOT, we have the character we wish to 
examine in the A register. 

But in either case, it's an exacting job. 

VIC-20 and Commodore 64 have made the job much more easy by pro- 
viding a vector at address $03Dfl/$D3Dq that will give us control of the 
computer, if we wish, immediately before each BASIC command is exe- 
cuted. We still need to use due care, but we have much more latitude. 



STACK, USR, INTERRUPT, AND WEDGE 



125 



The address of the instruction at C H R G T is often referred to as T X T P T R , 
the text pointer. This address always points to the BASIC command being 
executed at the moment. If we want to participate in reading BASIC, we 
must learn to use TXTPTR to get the information— usually by means of 
indirect, indexed addressing — and to leave this address pointing at a suit- 
able place when we return control bacl< to the normal BASIC handling 
programs. 

Project: Adding a Command 

Let's add a simple command to the VIC and Commodore 64 by using the 
$D3nfl vector. The ampersand (&) character isn't used in most BASIC 
programs, so we'll make it mean this: whenever you see the code "&", 
print ten asterisk (*) characters to the computer screen, followed by a 
carriage return. 

C128 note: Remember to check Appendix E, under Exercises for the 
Commodore 128, for the appropriate coding. 

As with our interrupt program, we'll copy the old address from $03Da/ 
03 into an indirect address location, so that we can link up with the 
normal computer routines as necessary. 

An important point: the vector will give us control, if we want it, with 
TXTPTR positioned immediately before the next instruction. When we 
return control to BASIC, we must be sure that TXTPTR is similarly po- 
sitioned. 

Here's our instruction "intercept": 

a 0330 LDY #$□! 

We're going to use indirect, indexed addressing to "look ahead" at the 
instruction. Let's look, using TXTPTR as an indirect address: 

A □33E LDA ($?&) ,Y 

Since Y equals one, we'll look just beyond the address to which TXTPTR 
is pointing: 

a Q3AQ CMP 

a BEQ $D3<7 

a U3AA JMP ($D3aD) 

If the character is an ampersand, we'll branch ahead to $0347. If not, 
we'll connect through the indirect vector to the regular BASIC interpreter 
code: 



726 MACHINE LANGUAGE FOR COMMODORE MACHINES 



ft U3A7 JSR $DD73 

We may call CHRGET to move the pointer along. Now TXTPTR points 
squarely at the ampersand character. We are ready to print ten asterisks: 



ft 


□ 3^ft 


LDY 


#$□□ 


ft 


Q3AC 


LDft 


#$2ft 


ft 


03<E 


JSR 


$FFDa 


ft 


□ 351 


INY 




ft 


0352 


cpy 


#$□& 


ft 


03SA 


BCC 


$a3^E 


ft 


035t 


LDft 


#$DD 


ft 


□ 35a 


JSR 


$FFDE 


ft 


□ 35B 


JMP 


$03AA 



The above code prints an asterisk ($2 ft) ten times and then prints a 
RETURN ($DD). It then goes to the regular BASIC interpreter, which will 
look behind the ampersand character for a new BASIC command. 

Now wei need to set up the link to our program. We'll write the code to do 
this starting at $D35E, so that SYS fibE will put the new command 
(ampersand) into effect: 



ft 


□ 35E 


LDft 


$D3Dfl 


ft 


□ 3bl 


STft 


$^3RD 


ft 


□ 3fc4 


LDft 


$D3DR 


ft 


□ 3t7 


STft 


$^3ftl 


ft 


□ 3fcR 


LDft 


#$3C 


ft 


□ 3fcC 


STft 


$D3^fl 


ft 


□ 3fcF 


LDft 


#$□3 


ft 


□ 371 


STft 


$D3^R 


ft 


□ 37^ 


RTS 





When you have completed and checked the code (remember this is for 
VIC and Commodore 64 only), return to BASIC. Type NEW and write the 
following program: 

lUO PRINT 3 A :&: PRINT 5 + b 
IIU & 

lED PRINT "THftT' S ftLL" 

If you type RUN, you will get a SYNTftX ERROR in line !□□. We have 
not yet implemented our "ampersand" command. Type the command SYS 
flfcE. Now type RUN again. The ampersand command obediently prints 
ten asterisks each time it is invoked. 

Infiltrating BASIC isn't an easy job. But it can be done. 



STACK, USR, INTERRUPT, AND WEDGE 



727 



Things You Have Learned 

—The stack is located in page 1, from SDIFF moving down to $0100. It is 
used for holding temporary information. A program may push information to 
the stack, and then pull it back later. The last item that has been pushed onto 
the stack will be the first item to be pulled back off. 

— Great care must be taken to ensure that your program pulls exactly the same 
number of items back from the stack as It pushed. In particular, be sure that 
a branch or jump does not inadvertently omit a needed stack activity. A badly 
handled stack is often fatal to the program run. 

— PHA pushes the contents of A to the stack; PLA pulls from the stack into 
the A register. These two commands are often used to temporarily save A. 
PHP pushes the status register (S R); PL A pulls it back. These two commands 
are often used for "deferred decisions." 

— JSR pushes a return address (minus 1) to the stack; ETS recalls this ad- 
dress. We may use JSR and RTS without needing to know the role the stack 
plays, since the two commands take care of the details for us. 

—Interrupts, including the BRK Instruction, push three items to the stack; RTI 
brings them back so that the interrupted program may resume. 

— USR is a function, as opposed to SYS, which is a command. DSR goes to 
a preset address, takes a numeric argument, and can return a value. In 
practice, DSR and SYS are used in quite similar ways. 

— Commodore ROM systems contain coding for the interrupt sequences that 
cause the data registers — A, X, and Y — to be pushed to the stack, and a 
branch to be taken through an indirect address that the user can modify. 
Since interrupt is active virtually all the time, it may be used to create activities 
that are active even when no BASIC program is running. 

— The various lA chips — PIA, VIA, and CIA — perform many different func- 
tions, including: recording events in latching flags and controlling Interrupts; 
timing; and connecting input/output ports. The detailed specification sheets 
must be studied for these rather complex details. 

—A subroutine called CHRGET is used frequently by the BASIC interpreter 
when a BASIC program is running. We may modify or add to this subroutine 
in order to add to or modify the BASIC language itself. 

Questions and Projects 

If you redirect the interrupt vector to your own machine language program, 
you can copy all of zero page to the screen. Use indexing; start X at zero; 
and walk through the whole of zero page, loading the memory contents 
and storing (indexed again, of course) to the screen. Don't forget to connect 
up your code to the regular interrupt entry address. 



128 MACHINE LANGUAGE FOR COMMODORE MACHINES 



You'll get a fascinating screen. There will be timers going, and as you 
type on the keyboard you'll see various inner values changing around. 
Enjoy the view. 

It's sometimes suggested that a good way to pass information to a sub- 
routine is to push the information onto the stack and call the subroutine. 
The subroutine can pull the information from the stack. What's wrong with 
this suggestion? 

The above suggestion can be implemented, but it takes a lot of careful 
stack work. You might like to work through the logic needed to do this. 

There are some utility programs which, when placed in the computer, 
allow a listing to be "scrolled." In other words, if the screen shows BASIC 
lines E 5 □ to < fc □, the user can take the cursor to the bottom of the screen 
and continue to press the cursor-down key. New BASIC lines (following 
AhO) will then appear. This is not an easy thing to code, but here's the 
question: do you think that this feature is done with a SYS command, a 
wedge, or an interrupt technique? Why? 

A SYS command from BASIC is like a subroutine call; so it must place 
an address on the stack to allow RTS to return to BASIC. Take a look at 
the stack and see if you can determine what address is used to return to 
BASIC on your machine. 



8 



Timing, 
Input/Output, 

and 

Conclusion 

This chapter discusses: 

• How to estimate the speed of your program 

• Input and output from tape, disk, and printer 

• Review of instructions 

• Debugging 

• Symbolic assemblers 

• Where to go from here 



131 



132 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Timing 



For many applications, maciiine language programs seem to run instan- 
taneously. The speed of the 650x is much greater than that of other 
devices, Including the human user. The machine language program usually 
ends up waiting for something: waiting for the keyboard, waiting for the 
printer, waiting for the disk, or waiting for the human to read and react to 
information presented on the screen. 

Occasionally, It may be Important to get fairly precise timing for a machine 
language program. If so, the following rules of thumb may be kept In mind: 

—All timing estimates are crude if the Interrupt routines are still active. The 
effect of interrupt on timing can be crudely estimated by adding 10 percent 
to the running time. 

—Remember to allow for loops. If an instruction within a loop Is repeated ten 

times, its timing will need to be counted ten times. 
—The "clock speed," or memory cycle speed, of most Commodore machines 

is roughly 1 microsecond — one millionth of a second. The precise number 

varies from one machine to another, and also varies between North America 

and other regions. 

—Most instructions run at the fastest imaginable speed. Count the memory 
cycles, and that's how fast the instruction will execute. For example, 
LDa #$DD will need two memory cycles just to get the instruction— and 
that's how fast it runs. LDR $0500 , X will usually take four memory cycles: 
three to get the Instruction, and one to fetch the data from page 5. Exceptions: 
no instruction runs in less than two cycles; and shift/rotate instructions, INC/ 
DEC, and JSR/RTS take longer than you might expect by this rule. 

—Branches time differently, depending on whether the branch is taken (three 
cycles) or not taken (two cycles). 

— When a page boundary is crossed, the computer needs an extra cycle to do 
the arithmetic. If the program branches from $DFE^to$lDa3, there will 
be an extra cycle; if we LDR $E^E7 , Y, there will be an extra cycle if Y 
contains a value of or greater. 

Detailed timing values can be obtained from most tables of instructions. 

Let's take a simple routine and estimate its timing. The following program 
logically RNDs the contents of IDQ locations from $17E0 to 



□ 33C 
n33E 
Q34D 
Q3A3 



LDX #$□□ 

LDA #$□□ 

AND $17ED,X 
INX 



TIMING, INPUT/OUTPUT, AND CONCLUSION 



133 



U3AS CPX 

03^7 BCC $D34D 

□3<q RTS 



We may work out timing as follows: 

LDX #$□□— executed once: 
LDA #$□□— executed once: 
AND $17ED , X: 32 times at 4 cycles: 



128 



2 



2 



68 times at 5 cycles (page cross): 
I NX— 100 times at 2 cycles: 
CPX 100 times at 2 cycles: 

BCC— 99 times at 3 cycles: 



340 



200 



200 



297 



1 time at 2 cycles (no branch): 
RTS— 6 cycles: 



2 



6 



Total time: 1171 cycles, or slightly over one thousandth of a second. We 
might add 10 percent to allow for the effects of interrupt; and since this is 
a subroutine, we could also add the extra six cycles needed to perform 
the JSR. 

Where timing is critical, the interrupt could be locl<ed out with SEI. Be 
careful: it's seldom necessary, and is potentially dangerous. 



We know that calling the kernal routine CHRODT at $FFD5 will send an 
ASCII character to the screen. We may also redirect output to any logical 
file. 

We have seen that we may obtain input from the keyboard buffer into the 
fi register by calling kernal routine GETIN at $FFE4. We may also 
redirect the input so that we draw information from any logical file. 

The same commands— $FFDE and $FFE4— still perform the input and 
output. But we "switch" either of them to connect to a chosen device — or 
more accurately, a chosen logical file. The file must be open; we may 
switch to the file, and then switch back to normal I/O as we wish. 



We use subroutine CHKODT at address $FFC9 to switch output to a 
logical file. When we want to restore output to the screen, we call sub- 
routine CLRCHN at $FFCC. This is not the same as an OPEN and 



Input and Output 



Switching Output 



134 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



KEYBOARD 




SCREEN 



INPUT 
DEVICES 

CHKIN ($FFC6) 

SETS THE 
INPUT SWITCH 



OUTPUT 
DEVICES 

CHKOUT ($FFC9) 

SETS THE 
OUTPUT SWITCH 



CLRCHN ($FFCC) 
RESTORES BOTH 
SWITCHES TO "NORMAL" 



Figure 8.1 

CLOSE— we simply connect to the file and disconnect, and we can do 
this as many times as we want. 



Subroutine: CHKOUT 
Address: $FFCq 

Action: Switclies the output path (used by CHROUT, $FFD5) 

so that output is directed to the logical file specified in the 
X register. The logical file must previously have been 
opened. 

The character subsequently sent by $FFDE is usually ASCII (or PET 
ASCII). When sent to the printer, special characters— text/graphics, 
width— will be honored in the usual way. Similarly, disk commands can 
be transmitted over secondary address 15 if desired; a logical "com- 
mand channel" file must be previously opened. 

Registers: Registers A and X will be changed during the CHKOUT 
call. Be sure to save any sensitive data in these registers before calling 
CHKOUT. 

Status: Status flags may be changed. In most recent Commodore 
machines, the C (carry) flag indicates some type of problem with con- 
necting to the output channel. 



To switch output to logical file 1, we would need to follow these steps: 



TIMING, INPUT/OUTPUT, AND CONCLUSION 



135 



1. Load a value of 1 into X (LDX #$□!). 

2. JSR to address $FFCq. 

Once the output is switched, we may send as many characters as we 
wish using subroutine $FFDE. Eventually, we must disconnect from the 
logical file and return to our default output, the screen. We do this by 
calling subroutine CLRCHN at address $FFCC. 



Subroutine: CLRCHN 
Address: $FFCC 

Action: Disconnects input and output from any logical files and 

restores them to the "default" input and output channels, 
keyboard and screen. The logical files are not closed, and 
may be reconnected at a later time. 

Registers: Registers A and X will be changed during the CLRCHN 
call. Be sure to save any sensitive data in these registers. 

Status: Status flags may be changed. In most recent Commodore 

machines the (carry) flag indicates some type of problem with output. 



The logical file concept is important. I may send to any destination — 
cassette, printer, disk, or screen— without knowing which device is in- 
volved. I send the characters on their way and the operating system sees 
that they are delivered wherever they need to go. 

This simplifies the machine language programmer's job. It's a simple task 
to send the characters to some logical channel; the programmer does not 
need to take special coding action depending on which device is involved. 

Output Example 

If we wanted to print the message HI on the printer, we might code as 
follows. 

0128 note: Remember to check Appendix E, under Exercises for the 
Commodore 128, for the appropriate coding. 

First, we'll open the printer channel in BASIC. Let's use logical file num- 
ber 1: 

IDO OPEN 1,A 

iiu SYS aaa 

lEO CLOSE 1 

If you don't have a printer, you may open the file to cassette (OPEN 



136 MACHINE LANGUAGE FOR COMMODORE MACHINES 



1 , 1 , E) or to disk (OPEN 1 , fl , 3 , " □ : DEMO , S , W"). The machine 
language program won't care: it will send to logical file number 1 no matter 
what it is; it might even be the screen (OPEN 1 , 3). Let's write the coding: 

A 0330 LDX #$□! 
a 033E JSR $FFCq 

Now the output is connected to logical file 1. Let's say HI: 



R 


□ 3<1 


LDA 




fi 


□ 3^3 


JSR 


$FFDE 


A 


□ 3-^^ 


LDA 




fi 


□ 3-^13 


JSE 


$FFDE 


A 


□ 34B 


LDA 


#$DD 


A 


□ 3^D 


JSR 


$FFDE 


A 


□ 350 


JSR 


$FFCC 


A 


0353 


RTS 





Don't forget to send the RETURN— the printer needs it. After the machine 
language program says HI, the program will return to BASIC and close 
the file. Notice that the machine language program doesn't care what it's 
saying HI to ... it sends the data to logical file 1. 

Switching Input 

We use subroutine CHKIN at address $FFCt to switch input so as to 
draw data from a logical file. When we want to restore input from the 
keyboard, we call subroutine CLRCHN at $FFCC. Again, this is not the 
same as an OPEN and CLOSE— we simply connect to the file and dis- 
connect, and we can do this as many times as we want. 

Subroutine: CHKIN 
Address: $FFCt 

Action: Switches the input path (used by GET, SFFE-;;) so that input is 

tai<en from the logical file specified in the X register. The logical 
file must previously have been opened. 

The character subsequently obtained by $FFE4 into the R register is usually 
ASCII (or PET ASCII). A binary zero received from a file usually represents exactly 
that: an input character whose value is CHR$(0); this is different from keyboard 
GET where a binary zero means "no key pressed." When accessing a file, ST 
(address $^0 for VIC and Commodore 64, for most PET/CBM) is used 
for its usual functions of signalling end-of-flle or error. Similarly, disk status in- 
formation can be received over secondary address 1 5 if desired; a logical "com- 
mand channel" file must be previously opened. 

Registers: Registers A and X will be changed during the CHKIN call. Be sure 
to save any sensitive data in these registers before calling CHKIN. 

Status: Status flags may be changed. In VIC and Commodore 64, the C (carry) 
flag indicates some type of problem with connecting to the input channel. 



TIMING, INPUT/OUTPUT, AND CONCLUSION 



737 



To switch input to logical file 1 , we would need to follow these steps: 

—Load a value of 1 into X (LDX #$01) 
— JSR to address $FFCE.. 

Once the input is switched, we may obtain as many characters as we wish 
using subroutine $FFE<. Eventually, we must disconnect from the logical 
file and return to our default input — ^the keyboard. We do this by calling 
subroutine CLRCHN at address $FFCC. This is the same subroutine that 
disconnects output from a logical file. 

Input Example 

We can write a program to read an input file from disl< or cassette. First, 
let's write the file. We open the file according to its type: 

Disk: OPEN l,a,3, "0:DEMO,S,W" 

Cassette: OPEN 1,1,1 

C128 note: Remember to check Appendix E, in the section. Exercises for 
the Commodore 128, for the appropriate coding. 

This may be done with a direct statement. Now let's write a few things to 
the file: 

PRINT#1, "HELLO THIS IS A TEST" 
PRINT#1, "THIS IS THE LAST LINE" 
CLOSE 1 

If we have typed in the above statements correctly, we should have a 
completed sequential file written on cassette or disk. Before writing the 
machine language input program, let's examine how we might read the 
file back in BASIC: 

Disk: IDO OPEN l,fl,3, "DEMO" 

Cassette: !□□ OPEN 1 

IID INPUT #1,X$ 

ISD PRINT X$ 

130 IF ST = D GOTO 110 

140 CLOSE 1 

We might alternatively have written lines 110 and 120 as 

110 GET #1,X$ 
lED PRINT X$ ; 

This more closely approximates the logic flow of our machine language 
program, since it will get the characters one at a time. If you are unsure 



738 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



about the role of ST, read up on it. We will use the same variable (at its 
address of $ R □ or $ R t) to do exactly the same thing in machine language. 

Type NEW and enter the following program: 
Disk: 100 OPEN 1, a, 3, "DEMO" 

Cassette: 100 OPEN 1 

110 SYS aaa 

lED CLOSE 1 

We will read the file and copy it to the screen entirely in machine language. 
Let's start coding at $ 0330 : 

a D33C LDX #$□! 
a □33E JSR $FFCt 

Now the input is connected to logical file 1. Let's get information from it 
and put it on the screen: 

a 03^1 JSR SFFE-^ 
a JSR $FFDE 

We must check ST as we would in BASIC. ST might be at either of two 
addresses, depending on the system: 

VIC, Commodore 64: R 03^7 LDR SRD 
CBM/PET: fi 03^7 LDA S^fc 

If ST is zero, there is more to come from the file; we may go back. If ST 
is nonzero, there could be an error or we may be at the end of the file. In 
either case, we don't want to read more from the file. 

ft DIA"^ BEQ $03-^1 
a □3'^B JSR $FFCC 
a Q3A-E RTS 

Check it and try it. The file is delivered to the screen quickly. 

A File Transfer Program 

Let's write a program to transfer a sequential file from any common device 
to any other. BASIC will sort out which files to handle; once the files are 
opened, machine language will take from and deliver to the appropriate 
logical devices as desired. 

C128 note: Remember to check Appendix E, in the section, Exercises for 
the Commodore 128, for the appropriate coding, both BASIC and machine 
language. 



TIMING, INPUT/OUTPUT, AND CONCLUSION 



739 



It's not a good idea to switch input and output at tiie same time — in otfier 
words, to call both $FFCt and $FFCR without canceling either via $FFCC. 
The l<ernal doesn't mind, but it confuses the peripheral devices, which 
expect to have exclusive occupancy of the data bus to the computer. So 
we'll follow the pattern: switching on, sending or receiving, switching off, 
and then going to the other device. 

One more thing. S T tells us the status of the last device handled. Consider: 
if we input a character, then output a character, and then checl< the value 
of ST, we have a problem. ST will not tell us about the input, since the 
last device handled was output; thus, we won't know if we are at the end 
of the file or not. In machine language, as in BASIC, we must code carefully 
to solve this problem. 

Here comes BASIC: 

lOD PRINT "FILE TRaNSFER" 

110 INPUT "INPUT FROM (DISK, TAPE)";A$ 

lEO IF LEFT$(a$,l) = "T" THEN OPEN 1:G0T0 IbD 

13D IF LEFT$(fi$,l)<> "D" GOTO IID 

l^D INPUT "DISK FILE NAME" ;N$ 

15D OPEN l,fl,3,N$ 

IbD INPUT "TO (DISK, TAPE, SCREEN)";B$ 

17 □ IF LEFT$(B$,1) = "S" THEN OPEN 2,3: GOTO 

IflD IF LEFT$(B$,1) = "D" GOTO aiD 

1^0 IF LEFT$(B$,1) <> "T" GOTO ItD 

^□0 IF LEFT$(A$,1) = "T" GOTO ItD 

21D INPUT "OUTPUT FILE NAME" ;F$ 

BED IF LEFT$(B$,1) = "D" 

THEN OPEN a,fl,^,"D:" + F$ + ",S,W" 

530 IF LEFT$(B$,1) = "T" THEN OPEN a,l,l,F$ 

BAD SYS XXXX 

ESQ CLOSE e:CLOSE 1 

We'll work this out for the Commodore 64 computer; you can adjust it for 
PET/CBM or VIC-20. The above BASIC program should not take up more 
than 511 bytes; on a standard Commodore 64, that means that we'll have 
clear space for our machine language program starting at $DAQD (dec- 
imal 55fc0). We'll move the start-of-variables along, of course, so that 
our machine language program won't be disturbed by them. 

When we first type line E^D, we won't know what SYS address to use. 
After the program is typed in (with SYS xxxxat line E< □), we can easily 
confirm that the machine language can start at $□ ADD by checking the 



140 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



start-of-variables pointer. We go back and change E^DtoSYS EBfcO; 
now we're ready to put in the machine language code: 

ft OftDD LDX #$□! 
ft DftDE JSR $FFCfc 
a OftDB JSR $FFE4 

By this time, we have a character in the ft register from the input source. 
We also have a value in ST, telling us if this is the last character. Let's 
examine the ST problem: we must check its value now, since ST will be 
changed after we do the output. But we don't want to take any action 
based on ST yet; we must first send the character we have received. Let's 
check ST, and put the results of the check onto the stack: 

ft DftDfl LDX $RD 
ft DftOft PHP 

If ST is zero, the Z flag will be set; we'll preserve this flag along with the 
others until we call it back from the stack. If you are adapting this program 
for the PET/CBM, don't forget that S T is at address $ R b for your machine. 

The next thing we want to do is to disconnect the input by calling $FFCC; 
but this will destroy the ft register. How can we preserve this value? By 
transferring to another register, or by pushing ft to the stack. Let's do that. 
There will now be two things on the stack. 

ft DftDB PHft 

We are now free to disconnect from the input channel and connect to the 
output. Here we go: 

ft OftOC JSR $FFCC 

ft DftOF LDX #$D2 

ft Dftll JSR $FFCH 

ft Dftl4 PLR 

The ft register gets back the last thing saved to the stack, and that, of 
course, is our input character. We're ready to send it to the output device: 

ft ORIS JSR $FFDE 
ft Oftia JSR $FFCC 

Now we may pick up on the condition of S T that we stacked away earlier. 
Here come the flags that we stored: 

ft DftlB PLP 



TIMING, INPUT/OUTPUT, AND CONCLUSION 



141 



If the Z flag is set, we want to go back and get another character. If not, 
we're finished and can return to BASIC, allowing BASIC to close the files 
for us: 

A OAIC BEQ $□&□□ 
a OaiE RTS 

Important: Before running this program, be sure to move the start-of- 
variables pointer ($DOeD/$OOEE) so that it points at address $DftlF; 
othenvise, the BASIC variables will destroy this program. 

Review: The Instruction Set 

We started with the load, save and compare for the three data registers: 

LDA LDX LDY 
STA STX STY 
CMP CPX CPY 

The instructions are almost identical in action, although only the A register 
has indirect, indexed addressing modes. We continued with the logical 
and arithmetic routines that apply only to A: 

AND ORA EOR ADC SBC 

Arithmetic also includes the shift and rotate instructions, which may be 
used on the A register or directly upon memory: 

ASL ROL LSR ROR 

Memory may also be directly modified by the increment and decrement 
instructions, which have related instructions that operate on X and Y: 

INC DEC 
INX DEX 
INY DEY 

We may transfer control by means of branch instructions, which are all 
conditional: 

BEQ BCS BMI BVS 
BNE BCC BPL BVC 

. The branch instructions can mal<e only short "hops"; the jump instruction 
is unconditional: 



JMP 



142 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Subroutines are called with the jump-subroutine, and returned with return- 
from-subroutine; we may also return from interrupts: 

JSR RTS RTI 

We may modify any of several flags with the appropriate set or clear 
command. Some of the flags control internal processor operation: for ex- 
ample, the I (interrupt disable) flag locks out the interrupt; the D (decimal 
mode) affects the way the ftDC and SBC work with numbers. 

SEC SEI SED 

CLC CLV CLI OLD 

We may transfer information between the A register and X or Y; and for 
checking or setting the stack location, we may move the stack pointer to 
X, or X to the stack pointer. The latter is a powerful command, so use it 
with care. 

TftX TRY TSX 
TXR TYfi TXS 

We may push or pull information from the stack: 

PHa PHP 
PLA PLP 

There's a special test, used mostly for checking I A chips: 
BIT 

The BIT test is used only for specific locations: no indexing is allowed. 
The high bit from the location being tested is transferred straight to the N 
flag. The next highest bit (bit b) goes straight to the V flag. Finally, the Z 
flag is set according to whether the location has any bits set that match 
bits set in the ft register. Thus, we can check a location with BIT $ ... . 
followed by BMI to test the high bit, or BVS to test bit fc, or BNE to test 
any selected bit or group of bits. It's a rather specialized instruction, but 
useful for testing input/output ports. 

Finally, the instruction that does nothing, and the BRK instruction that 
causes a "false interrupt," usually taking us to the monitor: 

NOP BRK 

That's the whole set. With these instructions, you can write programs to 
make the computer do whatever you choose. 



TIMING, INPUT/OUTPUT, AND CONCLUSION 



143 



Debugging 

When a program has been written, the next step is to look for any possible 
errors, or bugs. The process of searching for and systematically elimi- 
nating these bugs is called debugging. 

Most programs are made up of sections, each of which has a clear task 
to perform. When a program misbehaves, it may be easy to go to the area 
of the bug, since you can §ee which parts of the program are working and 
where things start to go wrong. 

In case of doubt, you may insert breakpoints into your program. Replace 
selected instructions with the instruction BRK; this may be done by re- 
placing the instructions' op codes with the value □□. Run the program; 
when it reaches the first breakpoint, it will stop and the machine language 
monitor will b^icome active. Examine the registers carefully to see whether 
they contain the values expected. Display memory locations that the pro- 
gram should have written; the contents will tell you whether the program 
has been doing its job correctly. 

When you have confirmed that the program is behaving correctly up to 
the breakpoint, replace the BRK command at that point with the original 
op code. Command . G to that address, and the program will continue to 
the next breakpoint. If it helps your investigation, you may even change 
memory or registers before continuing program execution. 

If you carried this procedure to the extreme, you might stop your program 
after every instruction. It would take time, but you would certainly track 
down everything the program did. 

The best debugging takes place at the time you write the program. Write 
sensibly, not "super cleverly." If you fear getting caught in an endless 
loop, insert a stop key test (JSR $FFE1) so that you'll still have control 
of the computer. 

Get to know your machine language monitor. The monitor uses a number 
of locations in memory; you'll have trouble debugging a program if it uses 
the same storage addresses as does your program. Every time you try to 
check the contents of a memory location to see what your program has 
done, you'll see the monitor working values instead — and that would be 
misleading and annoying. 

Symbolic Assemblers 

Throughout these exercises, we have used small, "nonsymbolic" assem- 
blers such as would be found within a machine language monitor. These 



144 MACHINE LANGUAGE FOR COMMODORE MACHINES 



are good for beginners; they parallel the machine code quite closely and 
allow you to keep the working machine clearly in focus. 

As you write bigger and better programs, these small assemblers will be 
less convenient. Forward, branches and subroutines we have not yet writ- 
ten make it necessary for us to "guess" at the address and fix up our 
guess later. There is the possible danger that an address will be typed in 
wrongly ($03^5 instead of $03 5^), causing the program to fail. 

To help us write more ambitious programs, we may wish to turn to com- 
mercially available assembler systems that allow labels or symbolic ad- 
dresses. If we wish to write code to call a subroutine to input numbers — 
we might not have written this subroutine yet— we can code JSR NUMIN. 
When we write the subroutine, we'll put the identifying label NUMIN at the 
start. As your program is assembled, the proper address of NUMIN is de- 
termined, and this address will be inserted as needed. 

It saves work and helps guard against errors. But symbolic assemblers 
allow a more powerful capability: they help documentation and allow pro- 
gram updating. 

Your assembly may be listed to the printer. This allows you to examine 
and annotate the program, and file the details away for later reference. 
The assembler allows you to include comments, which improve the read- 
ability of the listing but don't affect the machine language program. 

The source program you have written may be saved and used again later. 
If you find it is necessary to change the program, bring back the source 
code from cassette or disk, make the changes, and reassemble. In this 
way, programs can be easily corrected or updated. 

Where To Go From Here 

Almost anywhere. Up to this point, we've been building confidence: trying 
to give you a feel as to how the pieces work. Now, the real fun— the 
creative programming — is up to you. 

Users have varying objectives. You may want to do mathematical oper- 
ations. You may want to interact upon BASIC programs— analyzing, 
searching, renumbering. Whatever suits you. Your interest area may be 
music, graphics, or animation. Machine language will open the door to all 
of these; its amazing speed makes spectacular effects possible. You may 
plan to go into hardware and interface new devices to your computer; an 
understanding of machine language, and IR chips in particular, will be 
useful. The possibilities are endless. 



TIMING, INPUT/OUTPUT, AND CONCLUSION 



745 



Even if you have no immediate plans to write new programs in macliine 
language, you will have gained an insight into the worl<ings of your ma- 
chine. Everything that the machine does — BASIC, l<ernal, everything — is 
either hardware or machine language. 

With the elementary concepts we have introduced here, you will be able 
to go deeper into more advanced texts. Many programming books deal 
with the abstract 650x chip. That's hard for the beginner; it's difficult to 
see how the instructions fit within the architecture of a real machine, or 
how the programs can actually be placed within the computer. By now, 
you should be able to take a piece of abstract coding and fit it into your 
system. 

Many things start to happen at once when you take your first steps in 
machine language programming. You must learn how to use the monitor. 
You must learn a good deal about how your machine is designed. And 
you must learn how to fit the pieces together. It takes a while to adapt to 
the "information shock"— but things start to fit together. Eventually, you'll 
have a stronger and sounder view of the whole computer: hardware, soft- 
ware, languages, and usage. 

What You Have Learned 

— Machine language programs can have run times estimated fairly accurately. 
In many cases, however, machine language is so fast that detailed speed 
calculations are not needed. 

— We can handle input from devices other than the keyboard by switching the 
identity of the designated input device. If an input channel has been opened 
as a file, we may connect to it with JSE $FFCEj and disconnect with JSR 
$FFCC. 

— We can handle output to devices other than the screen by switching the 
identity of the designated output device. If an output channel has been opened 
as a file, we may connect to it with JSR $FFCR and disconnect with JSR 
$FFCC. 

— Once input or output has been switched, we may receive in the usual way 
with the subroutine at $F7EA, or send in the usual way with the subroutine 
at $FFDE. 

— Be careful not to confuse connecting to a channel with opening a file. In a 
typical program, we open a file only once, but we may connect to it and 
disconnect from it hundreds of times as we read or write data. 

— You have met all the instructions of the 650x microprocessor. There are 
enough for versatility, but not so many that you can't keep track of them all. 



146 MACHINE LANGUAGE FOR COMMODORE MACHINES 



You have made a worthwhile start in the art and science of machine language 
programming. 

Questions and Projects 

Write a program to read a sequential file and count the number of times 
the letter "A" (hex Al) appears in the file. Use a BASIC PEEK to print 
the value. You may assume that "A" will not appear more than 555 
times. 

Rewrite the above to count the number of occurrences of the RETURN 
character ($ DD) in a sequential file. Allow for up to b 5 5 3 5 appearances. 
Can you attach a meaning to this count? 

Write a program to print HAPPY NEW YEAR to the printer ten times. 

If you own a disk system, you know that you can scratch a program named 
JUNK by using the sequence: 

OPEN 15 , a , 15 : PRINT#15 , "SD : JUNK". Convert the PRINT# 
statement to machine language and write a program to scratch JUNK. 
Careful: don't scratch a program that you will need. 

Write a "typewriter" program to read a line of text from the keyboard and 
then transfer it to the printer. It will be a more useful program if you show 
what is being typed on the screen and if you write extra code to honor 
the DELETE key. 



A 



The 6502/ 

6510/6509/ 
7501/8500 

Instruction 
Set 

The four chips differ only in their use of addresses and 1 : 
On the 6502, the addresses are normal memory. 

On the 651 and 7501 , address □ is a directional register and address 1 Is an 
input/output register, used for such things as cassette tape and memory control. 

On the 6509, address □ Is used to switch program execution to a new memory 
bank; address 1 Is used to switch the memory bank accessed by the two 
instructions LDfl ( • • ) / Y and STA ( . . ) / Y- 



147 



148 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Addressing Modes 

Accumulator Addressing — This form of addressing is represented witfi a 
one byte instruction, implying an operation on the accumulator. 

Immediate Addressing — In immediate addressing, the operand is con- 
tained in the second byte of the instruction, with no further memory ad- 
dressing required. 

Absolute Addressing— \r\ absolute addressing, the second byte of the 
instruction specifies the eight low order bits of the effective address while 
the third byte specifies the eight high order bits. Thus, the absolute ad- 
dressing mode allows access to the entire 64K bytes of addressable mem- 
ory. 

Zero Page Addressing — The zero page instructions allow for shorter code 
and execution times by only fetching the second byte of the instruction 
and assuming a zero high address byte. Careful use of the zero page can 
result in significant increase in code efficiency. 

Indexed Zero Page Addressing— (X, Y indexing)— This form of address- 
ing is used in conjunction with the index register and is referred to as 
"Zero Page, X" or "Zero Page, Y." The effective address is calculated by 
adding the second byte to the contents of the index register. Since this is 
a form of "Zero Page" addressing, the content of the second byte refer- 
ences a location in page zero. Additionally, due to the "Zero Page" ad- 
dressing nature of this mode, no carry is added to the high order eight 
bits of memory and crossing of page boundaries does not occur. 

Indexed Absolute Addressing— {X, Y indexing)— This form of addressing 
is used in conjunction with X and Y index register and is referred to as 
"Absolute, X," and "Absolute, Y." The effective address is formed by 
adding the contents of X and Y to the address contained in the second 
and third bytes of the instruction. This mode allows the index register to 
contain the index or count value and the instruction to contain the base 
address. This type of indexing allows any location referencing and the 
index to modify multiple fields resulting in reduced coding and execution 
time. 

Implied Addressing— \n the implied addressing mode, the address con- 
taining the operand is implicitly stated in the operation code of the instruc- 
tion. 

Relative Address/ng— Relative addressing is used only with branch in- 
structions and establishes a destination for the conditional branch. 

The second byte of the instruction becomes the operand which is an 
"Offset" added to the contents of the lower eight bits of the program counter 



APPENDIX A 



149 



when the counter is set at the next instruction. The range of the offset is 
-lEflto +127 bytes from the next instruction. 

Indexed Indirect Addressing— \n indexed indirect addressing (referred to 
as [Indirect, X]), the second byte of the instruction is added to the contents 
of the X index register, discarding the carry. The result of this addition 
points to a memory location on page zero whose contents are the low 
order eight bits of the effective address. The next memory location in page 
zero contains the high order eight bits of the effective address. Both mem- 
ory locations specifying the high and low order bytes of the effective ad- 
dress must be in page zero. 

Indirect Indexed Addressing— \n indirect indexed addressing (referred to 
as [Indirect, Y]), the second byte of the instruction points to a memory 
location in page zero. The contents of this memory location are added to 
the contents of the Y index register, the result being the low order eight 
bits of the effective address. The carry from this addition is added to the 
contents of the next page zero memory location, the result being the high 
order eight bits of the effective address. 

Absolute Indirect— The second byte of the instruction contains the low 
order eight bits of a memory location. The high order eight bits of that 
memory location is contained in the third byte of the instruction. The con- 
tents of the fully specified memory location are the low order byte of the 
effective address. The next memory location contains the high order byte 
of the effective address which is loaded into the sixteen bits of the program 
counter. 



Instruction Set — Alphabetic Sequence 



ftSL 



RDC 



AND 



Add Memory to Accumulator with Carry 

"AND" Memory with Accumulator 

Shift Left One Bit (Memory or Accumulator) 



BEQ 
BIT 



BCC 



BCS 



Branch on Carry Clear 
Branch on Carry Set 
Branch on Result Zero 



BNE 



BMI 



Test Bits in Memory with Accumulator 
Branch on Result Minus 
Branch on Result not Zero 



BPL 



BRK 



Branch on Result Plus 
Force Break 



750 MACHINE LANGUAGE FOR COMMODORE MACHINES 



BVC 


Branch on Overflow Clear 


BVS 


Branch on Overflow Set 


CLC 


Clear Carry Flag 


CLD 


Clear Decimal Mode 


CLI 


Clear Interrupt Disable Bit 


CLV 


Clear Overflow Flag 


CMP 


Compare Memory and Accumulator 


CPX 


Compare Memory and Index X 


CPY 


Compare Memory and Index Y 


DEC 


uecremeni Memory uy vjne 


DEX 


Decrement Index X by One 


DEY 


Decrement Index Y by One 


EOR 


"Exclusive-OR" Memory with Accumulator 


INL 


incremeni iviernory oy kjuxs 


T \T V 

INX 


incremeni inaex a uy une 


T M V 

IN I 


incremeni inaex y oy v_»ne 


JMP 


Jump to New Location 


JSR 


Jump to New Location Saving Return Address 


LDfi 


Load Accumulator with Memory 


LDX 


Load Index X with Memory 


LDY 


Load Index Y with IVjemory 


LSR 


Shift One Bit Right (Memory or Accumulator) 


NOP 


No Operation 


OR A 


"OR" Memorv with Accumulator 


PHA 


Push Accumulator on Stack 


PHP 


Push Processor Status on Stacl< 


PLR 


Pull Accumulator from Stack 


PLP 


Pull Processor Status from Stack 


ROL 


Rotate One Bit Left (Memory or Accumulator) 


ROR 


Rotate One Bit Right (Memory or Accumulator) 


RTI 


Return from Interrupt 



APPENDIX A 



151 



RTS 


Return from Subroutine 


SBC 


Subtract Memory from Accumulator with Borrow 


SEC 


Set Carry Flag 


SED 


Set Decinmai Mode 


SEI 


Set Interrupt Disable Status 


STfl 


Store Accumulator in Memory 


SIX 


Store Index X In Memory 


STY 


Store Index Y in Memory 


TAX 


Transfei- Accumulator to Index X 


TAY 


Transfer Accumulator to Index Y 


TSX 


Transfer Stack Pointer to Index X 


Txa 


Transfer Index X to Accumulator 


TXS 


Transfer Index X to Stack Register 


TYfl 


Transfer Index Y to Accumulator 



Programming Model 



15 



PCH 



8 7 



PCL 



N 


V 




B 


D 


1 


Z 


c 



ACCUMULATOR A 

INDEX REGISTER Y 

INDEX REGISTER X 

PROGRAM COUNTER "PC" 

STACK POINTER "S" 

PROCESSOR STATUS REG "P" 



L 



CARRY 1 = TRUE 

ZERO 1 = RESULT ZERO 

► IRQ DISABLE 1 = DISABLE 

► DECIMAL MODE 1 = TRUE 

► BRK COMMAND 



OVERFLOW 
NEGATIVE 



1 = TRUE 
1 = NEG 



Figure A.1 



152 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



<« 


HI 

m 






O 
CO 




<" 


LU LLl LU UJ LU LU 

r- CO If) Q u. 


LU 


mco 
< 


ooooo 

CM00<OUJ 


can 
< 


LULUUJLiJUJLLlLiJLLJ 


1 

o 


X-CM 
N 


0)DO 


ZPAG Z,X Z,Y 
2 2 2 


(Ota 

0>ffi 

(0 CO CO (O (o 
,-coior^ Qu. 


CO 

1 

c<r 
1 


a 


CM00<OUJ 

OOO 
<OUJ 


tocococococococo 

O CM Tt <o 00 < CJ UJ 


(0 
T3 

c 

(U 
0) 




00(0 jOO 




CM 

< 


■o 
o 

o 










<a:!llEC<oIliQs 


a 
O 












5 
z 


o 

CO 




„X A,Y 
3 3 


oojoxn 0)0)0)0) 
»- CO in 0) 00 Q u- 

OaOQQOOO 
t- CO in 0) OQ Q u. 

QQQDQQQQ 
O CM 't CO 00 < O UJ 




C/) 
OQ 
< 


oo 


to 
a 

E 

3 
—> 


< 

(0 

coco 


Q 

1 




-)-) 




< 

XcM 


»-coinr>-0)OQQLL 

OCS'*<000<OIU 

in in u) in in in in in 
«-coinr*o>0QQu. 

in in in in in in in in 

OCM^(000<UUJ 


o 

<J> 
1 

in 








o 

<CM 

0. 

N 


1 
1 

,c 
(/> 

T3 
C 


oooo 
cor^cou. 

2>UUJ 
OQ CO QQ DO 


o 

1 

<o 

0) 


O) 0) 0) 0) 0) 0) 0) 
O CM CO < O UJ 


0) 
<D 

•a 
o 
O 


OOOO 

in o>Q 


u 
c 

i2 

00 




<QcnO<<£:o 
$200^=0^00 
0<llJ<C/)_lO(0 


a 
O 


_jOOuj 

q:>oz 

OQ 00 00 OQ 





1 

u. 


SED 


1 

Ul 


^ a. 

ii 


1 

Q 


CLD 


1 

o 


>-X 

Is 


1 

oo 




1 

< 


>-x 


1 

0) 


<(/) 


1 

00 


qh 


1 

r~ 


u] 
(/) 


1 

CO 


RTS 
PLA 
ROR-A 


1 

in 


CLI 


1 

■>t 


RTI 
PHA 
LSR-A 


1 

CO 


SEC 


1 

CN 


PLP 

ROL-A 


1 


CLC 


1 

o 


BRK 
PHP 

ASL-A 




Ooo< 
1 1 1 



in 
<u 

■D 
O 

o 

a 
O 

O) 

c 

(A 



CM 
< 

S 
3 

g> 

IL 



APPENDIX A 



153 



CONDITION 
CODES 


N Z C 1 V 1 


\ 

\ 
\ 
\ 


1 

\ 
\ 


\ 
\ 
\ 








s 

; 

\ 

2 








1 






1 


° 

1 
1 


1 

o 

1 

1 


o 


1 

V 

\ 


1 

\ 


1 

\ 

\ 
\ 


j 

\ 
\ 


1 

\ 
\ 


V 
V 


1 

\ 
\ 


1 

\ 
\ 


1 

\ 
\ 


1 

I 

V 
V 




1 

1 


1 

\ 

\ 


> 

i 


% 






























































z 
































































o 






























































1 


% 






























































■o 


z 






























































c 


CL 

o 






























































lative 










CM 


CM 


cy 




CM 


CM 


CM 




CM 


CM 




































z 




















— 






<M 




































o 
c 


a. 

O 












£ 






s 


° 




s 






































>■ 


=* 


m 


m 
































m 












to 












CO 




z 
































































Q. 

o 




































s 
























& 


X 






CO 






































CO 






to 


CO 










CO 




z 










































I- 






•V 


N. 










rr 




Q. 

o 




« 
































o 

a 






UJ 

o 






o 

m 


LU 
LJ. 










o 

CD 


X 








CM 






























CM 






CM 






CM 


CM 










CM 


to 

i 


z 










































CO 








<D 










«!■ 


NT 


□l 
O 




































o 














S 












> 


=* 


CJ 


N 
































CM 












™ 












CM 




z 




































to 












to 












u> 


c 


Q. 

o 




n 
































a 












ID 












m 


X 


% 


N 


CM 
































<M 












CM 












CM 


li 


z 




































CO 












CO 












CO 


e 


0. 

o 


to 


w 
































5 
























< 


piled 


* 






















- 






- 






- 










- 


- 
















z 




























cy 


CM 


CM 


CM 










CM 


eg 






CM 


CM 








E 


Q. 

o 






















s 






GO 


CO 
O 


s 


s 










g 


s 






CO 
tli 


8 








E 








- 
























































z 






CJ 


























































Q. 

o 






s 
























































d> 




CM 


CM 


CM 








CM 


































CM 


CM 














Z 




CO 


Ul 








to 


























n 


m 






CO 


in 










CO 


o 


Q. 
O 




in 

CM 


S 






























m 
O 


^ 
LU 


3 


to 
O 






in 
-t 


CO 

LU 
















« 


to 


to 








CO 






















to 


to 


to 


CO 






CO 


CO 






CO 




to 


1 


z 






to 




































to 








CO 






CO 


to 


•V 




a. 
o 


Q 

CO 


Q 

(N 


UJ 
o 






























Q 

O 


O 
tu 


O 
O 


LU 
O 






O 


UJ 
UJ 








8 


o 
< 




% 


CO 


cv 
































CM 


CM 


CM 




















CM 


? 


z 


CM 


CM 
































CM 




CM 








CM 












CM 


E 

e 


Q. 

O 


•B 

(0 


o> 

CM 
































O 




8 




















5 


NSTRUCTIONS 


c 
_g 

(5 

& 

o 


< 

T 

o 
+ 

+ 
< 


< 

T 

s 

% 


2 

o 

1 

o 


o 
O 

z 
o 
I 
o 
z 
< 

(£ 
03 


o 
z 
o 

X 

o 
z 
< 
a: 

03 


N 
Z 

o 

X 

o 
z 
< 

X 
03 


$ 


z 
z 
o 
I 
o 
z 
< 

03 


o 

11 

N 

z 
O 
X 

o 
z 
< 

tE 

m 


o 

z 
z 

o 

X 

o 
z 
< 

CE 
03 


< 

o> 
u, 
a 

9 
« 


o 

> 
z 
o 

X 

o 
z 

2 

03 


> 
Z 

o 

X 

u 
z 
< 
cc 

CD 


O 

T 

o 


O 

T 

o 


T 

o 


> 


< 


X 


> 


s 

I 


X 

J; 

X 


> 
> 


< 

T 

> 
< 


S 

X 

+ 


X 

I 

+ 

X 


> 

+ 
>- 


d 
O 
_j 

UJ 

z 

R 

-J 


CM 
< 

!> 03 
3. 3 
w w 

II 


< 
T 

2 




o 
c 
o 
E 

s 


o 
a 
< 


o 
< 


w 
< 


O 
O 
CD 


w 
o 
m 


2 

m 


1- 


S 

CO 


UJ 

z 

CO 


—I 
Q. 
CD 


CC 
CO 


O 
> 
03 




O 

o 


O 
_i 

o 


O 


> 
d 


O 


X 
Q. 
O 


>- 

0. 

o 


o 

LU 

o 


X 
UJ 

o 


> 

LU 
O 


cc 
o 

UJ 


O 
z 


X 

z 


> 

Z 


0- 
2 
-> 


cc 


< 
o 

_1 



CO 
<t 
£ 

3 

o> 
il 



154 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



CODES 


N Z C 1 V 


1 

1 
1 

\ 
\ 


1 1 
1 1 
1 1 
1 \ 
\ \ 

\ c 


1 

; 

1 


1 
1 

1 

V 
\ 


; 


1 

; 


1 

1 
1 

\ 
\ 


(RESTORED) 


1 
1 

\ 
\ 
\ 


1 

\ 
\ 
\ 


(RESTORED) 


1 


\ 

1 

\ 
\ 


1 

1 


1 


I 

1 
j 


1 

1 


1 


1 


1 

1 

\ 

\ 


1 

1 

\ 


1 

1 

\ 


i 

! 

>^ 
\ 


1 


1 

\ 
















— 
























OJ 


















z 




































t 
















1 
hi 


O 


tp 

s 




















































% 






















































z 




















































1 


Q. 

o 










































































































1 


Z 




















































0. 

o 




















































> 
1 




n 






CO 


















CO 








CO 


















z 


































m 


















o 


tu 
m 


















































K 


H: 




« c 


o 


o 










n 


CO 






CO 








CO 


















Z 




■* r 






























in 


















Ol 
O 




Q L 

m I 


u 

n 


O 










LU 


UJ 






Q 








a 


















Z, Page, xl 






CM 


>r 


CM 










CM 


CM 






CM 








CM 




OJ 














z 






D 












CD 


CO 


















V 












o 




m 




m 












(D 






LO 












s 














(lnd.)Y 1 










lO 


















CM 








CM 


















z 








u> 


















in 








to 


















0. 

o 


























tu 


























X 

T 
« 










CM 


















M 








CM 


















z 








CO 


















CO 








CD 


















0. 

o 








o 


















UJ 








5 


















Implied 1 


tb 




























T- 
























z 






CM 




CO 


CO 










CO 


to 




(M 


CM 


CM 








CM 


CM 


CM 


CM 


CM 


CM 


fe 






<; 

UJ 




C9 


3 


to 


CO 
CM 






o 


3 






LL 












< 


< 




< 


m 


Accum. 1 


% 




















































z 






CM 












CM 


CM 
































0. 

o 




















































Zero Page 1 




CM 


CM 


CM 


CM 












CM 






CM 








CM 






















n 




P5 










in 


in 






CO 








n 




to 














Q. 

o 


(O 
< 


< 


« 














s 






in 

UJ 








S 


















Absolute 1 






CO 


(0 












CO 


CO 






<0 








CO 




(O 














z 






(D 












(D 


<D 














xr 


















Q. 

o 


lU 

< 




UJ 

T 


O 
o 










lU 
CM 


UJ 






Q 
LU 








Q 

CO 


m 

CO 


o 

eo 














1 

i 

E 


% 


CM 


CM 






















CM 


























z 


CM 


CM 






















CM 


























a. 
o 


a 






s 


















o> 

UJ 


























INSTRUCTIONS 1 


c 
< 

! 
1 


X 

: 


> 


i i 


< 


03 

to 

(0 

s 
- 


j: 

CO 
0] 

S 


< 

01 

X 

+ 


Q. 

CO 

t 

+ 

(0 


i 


b 


i- 


«i: 

9 CO 

.i> M 

Z 

OJ DC 


< 

< 


O 

T 


Q 

j; 


I 




2 


I 


X 

< 


> 

i 


X 

<i 


< 


CO 


■< 


s 

1 

S 


X 

3 


>- 

3 


§ 1 


< 

o 


0. 


a 

X 
0. 


3 

Q. 


0. 


§ 


cc 




!2 


o 
cc 

CO 


o 

Ul 


o 

UJ 
0> 


u) 
m 








X 

? 


> 


X 

S2 




CO 





U; m cQ 

Q Q s. > 

a O £ £ 

U: s s g 

e )- s 2 



O CD O „ O 

S3 Z S X 
CO < O UJ 



12 



b ^ 
UJ u 
u. < 

U. I- 

UJ CO 
O (£ IT 

H m UJ 

^ D. CL 
S CC flC 

X X 5 o O 

UJ LU 8 s 2 

ilSss 

X 5- < S ^ 



O S UJ 
UJ 0- oc 

Sis; 

O S St 

„ p p 



>- w tfl 

c {E cr 

< =J 3 
o o o 
zoo 
=1 o o 

§55 

UJ z z 

0. m m 

U. 

z z z 

*- CM 

o o o 

O C3 Q 

< < < 



o N 

9 ° 



53 



B 

Some 
Characteristics 
of Commodore 
Machines 



755 



156 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



PET— Original ROM 

The first PET. It can be recognized by tlie message seen at power up: 

*** COMMODORE BASIC *** 

using asterisks but witli no identifying number after tlie word BASIC. 

The original machine may be upgraded to Upgrade ROM by fitting a new 
set of ROM chips. This is a good idea, since the original logic cannot 
handle disk, does a poor job on cassette data files, has no built-in machine 
language monitor, and has a zero page architecture that differs significantly 
from all later PET/CBM's. The BASIC language on this unit is also limited; 
arrays may not contain over 256 elements, for example. 

This early machine is becoming rare. 

PETICBM— Upgrade ROM 

The first PET that can handle disk. It can be recognized by the message 
seen at power up: 

### COMMODORE BRSIC ### 
using the numbers sign (or octothorpe, if you like). 

This is much cleaner logic than the previous machine. Its internal structure 
is similar to that of later PET/CBM units (the 4.0 machines), so that it has 
much in common with them. 

It does not have specialized disk commands such as CRTRLOG, 
SCRATCH, or DLOAD (the 4.0 disk commands); but these are "conve- 
nience" commands and the Upgrade ROM unit can do everything that the 
later units do. 

Upgrade ROM machines have a BASIC annoyance: under some circum- 
stances, string variables need to be tidied up using a technique called 
"garbage collection." This takes place automatically when needed; but 
when it does, the machine will freeze and seemingly will be dead for a 
period that may last from a few seconds to as long as a half hour or more. 

PETICBM— 4.0 ROM and 80 Characters 

This class of machine has been a mainstay of the Commodore line for 
years. It may be recognized by the message seen at power up: 

*** COMMODORE BASIC A . D *** 

For the first time, a number appears in the message. 



APPENDIX B 



157 



These machines are characterized by new BASIC disk commands 
(CATaLOG, etc.) and elimination of garbage-collection delays. Their in- 
ternal architecture, especially zero page, is quite similar to the previous 
Upgrade ROM computers. 

Some time after the initial production of 40-column machines, 80-coiumn 
machines were introduced, as well as a new 40-column version called the 
"fat 40." The later machines are distinguished by new screen/keyboard 
features, most noticeable of which is that the cursor movement keys repeat 
automatically. 

Subsequently, two memory-expanded machines became available. The 
8096 came fitted with 96K of RAM; the extra 64K was "bank switched" 
into memory as needed in blocks of 16K. The SuperPET, too, had an 
extra 64K of RAM that was bank switched in 4K blocks; it also came with 
an additional microprocessor (the 6809) used primarily for implementing 
high-level languages. Both the 8096 and the SuperPET may be used as 
conventional CBM 8032 computers; the extra memory may be ignored. 

VIC-20 

The VIC-20 was a new design concept for Commodore. Color, graphics, 
and sound were built into the computer. The memory architecture changed 
radically. Zero-page locations were shifted significantly as compared to 
previous PET/CBM computers. 

BASIC reverted to Upgrade ROM style — no special disk commands and 
potentially slow garbage collection. Other than that, BASIC was not trimmed. 
All the functions and features remained, and some attractive new screen 
editing features were added, such as automatic repeating keys. 

The VIC comes with no machine language monitor; it's necessary to load 
one. The SYS command has a new attractive feature that allows registers 
A, X, and Y to be "preloaded" by POKGing values into addresses 780, 
781 , and 782. Location 783 could also be used to set the status register, 
but that's dangerous; unless it's done carefully, the decimal mode or in- 
terrupt disable flags might be set inadvertently. 

The VIC-20 is somewhat vexing for machine language programming work. 
Depending on the amount of extra memory fitted (none, 3K, or 8K and 
over), the location of start-of-BASIC and of screen memory will vary. 

Commodore 64 

The Commodore 64 has much in common with the VIC-20. In particular, 
its zero page organization is almost identical to that of VIC. The Com- 



158 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



modore 64 comes with a 6510 microprocessor; addresses □ and 1 are 
reserved for "banl< switching" of memory. 

BASIC is identical to that of the VIC— no special disk commands and 
potentially slow garbage collection. There's no built-in machine language 
monitor, so one must be loaded. The SYS command, as with the VIC, 
allows preloading of registers R, X, and I if desired. 

The Commodore 64 has a more stable architecture than the VIC. BASIC 
starts in a consistent place, and the screen is always at hex 00 unless 
you move it. There's a bank of memory at $CODD to $CFFF that is not 
used by the computer system; it's useful for staging machine language 
coding. 

The Commodore 64 is the first Commodore machine in which it is some- 
times desirable to write totally in machine language, with no BASIC at all. 
BASIC can be swapped out to release extra RAM, and large applications 
(word processors, spread sheets, and so on) are likely to do this. 

Commodore PLUS/4 

Similar to the Commodore 64 in many ways. The processor is a 7501 , 
which has the same instruction set as the 6502. Screen memory and 
BASIC RAM have been moved a little higher. BASIC itself is greatly ex- 
panded. 

Color and sound are implemented differently to the Commodore 64. 

There's a built-in machine language monitor with expanded features, such 
as assemble and disassemble. This one is convenient for machine lan- 
guage programmers. 

The memory arrangement is more sophisticated than on previous ma- 
chines; large implementations may require insight into the machine's de- 
tailed architecture. 

B Series 

The B-128, B-256, CBM-128, and CBM-256 were designed as successors 
to the 80-column PET/CBM units. Architecture has been radically changed: 
the processor is a 6509, memory is bank switched, and zero page is 
significantly different from that of other models. 

The cassette buffer is no longer at $033 □, so that the examples given 
in this book will need to be moved to a new part of RRM (addresses 
$□'';□□ to $n7FF are available). Bank switching is more complex than 
on other models. Beginners will find that there are more things to be kept 



APPENDIX B 



159 



track of in this machine. If possible, beginners should try to find a simpler 
computer on which to take their first steps. 

Implementation of large-scale programs require setting up a "transfer se- 
quence" program to link the program's memory bank to that of the kernal. 
Usually, a bootstrap program will be needed to set everything up. 

A machine language monitor is built into this line of machines. A few new 
commands have been made available: . V to switch banks, . @ to test 
disk status. 



160 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Commodore 128 

The Commodore 128 is three machines in one. 

1 . In C64 mode, It Is Identical In almost all aspects to the Commodore 64. As 
such, the machine In this mode has access to only 64K of memory, and 
normally uses only standard Commodore 64 peripherals and screen formats. 

2. In CI 28 mode, It Is an extended version of the 64 with extra features: 128K 
of memory (arranged In two banks of 64K per bank); the possibility of using 
an 80-column screen; the possibility of interfacing a disk unit that will operate 
at a much higher speed than that of the Commodore 64. 

The C128 has extensive hardware compatibility with the Commodore 64. 
The 64's standard disk and printer can be hooked up in the usual way, but 
with no speed Improvement. Sound and 40-column graphics may be achieved 
with POKES to the same memory locations as for the 64. 

The processor used for the C64 and CI 28 is the 8500, which has the same 
instruction set as other machines such as the Commodore 64. Machine 
language software Is not generally upwardly compatible with the Commodore 
64 because of differing RAM usage between the two machines. 

3. CP/M mode uses the Z80-A microprocessor, whose machine language in- 
struction set is completely different from that of the 650x. These are outside 
the scope of this book. 

Introduction (128) 

The Commodore 128 may be used as if it were a Commodore 64 or in 
CP/M mode. The following material deals with its use in CI 28 mode. 

The Commodore 128 comes with a 8501 microprocessor. As in the Com- 
modore 64, addresses □ and 1 are reserved for control ports. 

BASIC is rich with extra commands, and there's a good built-in machine 
language monitor, which will be useful for us. The SYS command allows 
preloading of registers A, X, and Y if desired, and reading the contents 
of these registers after a return to BASIC. 

The Commodore 128 has a large amount of memory, and this calls for 
an elaborate architecture. There is 128K of RAM, 44K of ROM, the input/ 
output chips, and the potential for much more ROM and RAM to be added 
internally or through a cartridge. The processor can reach only 64K of 
memory at a time, so that a sophisticated system of "memory banl<ing" 
must be used to get access to everything. 

The term "bank" is misleading; the word "configuration" might be more 
appropriate. For example, when a programmer calls for BANK 13 the 



APPENDIX B — COMMODORE 128 



161 



computer supplies a configuration which is partly RAM and partly ROM. A 
call for BANK 1 5 would invoke a different configuration of RAM and ROM. 
Some of the RAM and ROM are the same as in the previous configuration. 
The details are not important at this stage, but a drawing of some of the 
popular "bank" configurations might be helpful. 

In this book, we will be using Bank 15 almost exclusively. That will allow 
us to put our own programs into RAM at a low address in memory, and 
call upon the built-in programs that are stored in ROM at high memory 
addresses. 

Since the Commodore 128 contains a "built-in" Commodore 64, it will not 
be surprising to learn that many of the interface chips — for video, sound, 
and other purposes— are almost identical to those of the Commodore 64. 

Do not worry if all this sounds technical. You will learn about many of 
these features as you go. 

Here's the important thing to remember: when you reach the exercises 
that are found in each chapter, check Appendix E, under Exercises for 
the Commodore 128, to get the CI 28 version. The principles are the 
same — we're doing the same thing using the same techniques — but small 
adjustments are needed for the special characteristics of the Commodore 
128. 

If you have not read the main part of the book, stop here and return to 
Chapter 1 . When you're ready to dig for more technical information, you 
will find it here, and in Appendix E and Appendix C and Appendix H. But 
first: read, learn, and enjoy. 

Choosing a Bank for Your Program (128) 

You can move from one bank to another, but it takes extra work. It's best, 
when you can, to pick an initial bank configuration that you can live with 
during the running of your program. A quick rundown of the most popular 
configurations follows. Choose Bank 15 if you can. 

First, a general rule: Addresses □ and 1 are reserved, and so are ad- 
dresses hexadecimal FFDO to These addresses don't "bank" and 
are always there. The 251 addresses above $FFD4 are bank switched, 
but are seldom useful to the average programmer. In a standard C128, 
addresses from $3to$D3FF always refer to RAM Bank regardless of 
the bank selected. 

Banks 0, 1, 2, and 3 are pure RAM— no ROM to help you do things, no 
I/O chips to help you input and output data. Banks 2 and 3 are reserved 



162 MACHINE LANGUAGE FOR COMMODORE MACHINES 



FEFF 



$00(^ 



"Bank 0"— Almost 64K of RAM. This is where BASIC programs are stored. RAM exists 
above $FF04, but is not nomiaiiy used. 




"Bank 1 "—Addresses from $0400 up are RAM 1 , where BASIC variables, arrays, and strings 
are stored. Below $0400, RAM is used. 




"Bank 1 3"— Below $8000, addresses RAM 0. Cartridge ROM (if present) occupies addresses 
$8000 to $BFFF. From $000 to $FFFF, we have Kernal ROM, except for the area from 
$D000 to $DFFF, which holds input/output chips. 



APPENDIX B — COMMODORE 128 



763 



$0000 $E000 




"Bank 14"— Memory below $4000 is RAM 0. From $4000 up, we have ROM for BASIC and 
Kernel, except for a slot from $0000 to $OFFF, which contains the character generator ROM. 




"Bank 15 '—Memory below $4000 is RAM 0. From $4000 up, we have ROM for BASIC and 
Kemal except for a slot from $0000 to $OFFF, which contains input/output chips. 



764 MACHINE LANGUAGE FOR COMMODORE MACHINES 



for the addition of extra RAM. None of tliese are good configurations for 
programs — you will always want to do input and output — but they are 
often called in briefly to get or store data. Banl< uses the RAM that 
normally holds BASIC programs; Bank 1 uses the RAM that holds BASIC 
variables, arrays, and strings. 

Banks 4, 5, 6, and 7 are similar to Banks 0-3 below address $flODO. A 
set of ROM lies over the RAM at addresses $flDDDto$FFFF, except 
for addresses $DDDD to $DFFF which contain I/O chip registers. This 
ROM is internal, which means that it can be plugged into spare sockets 
within the C128. Unless you plan to make your own ROM-like chips, in- 
cluding your own Kernel program, stay away from these. 

Banks 8, 9, 10, and 11 are similar to Banks 0-3 below address SflDDD. 
A set of ROM lies over the RAM at addresses SflODQ to $FFFF, except 
for addresses $DDDD to $DFFF which contain I/O chip registers. This 
ROM is external, which means that it is plugged into the cartridge port. 
Again, stay away; using these configurations calls for you to supply the 
entire logic of the machine. 

Banks 12 and 13 are similar to Bank below address $flODD. A set of 
ROM (internal for Bank 12, external for Bank 13) lies over the RAM at 
addresses IfiODD to $BFFF, and the standard Kernal ROM lies over 
the RAM at addresses $CDDD to $FFFF, except for addresses $DODO 
to $DFFF which contain I/O chip registers. These look good for the 
average application if you don't need BASIC. You'll get lots of RAM memory 
to play with, yet the I/O chips and Kernal are there and available to you. 

Banks 14 and 15 are similar to Bank below address $^00D. System 
ROM (Basic and Kernal) lies over the RAM at addresses OOD to $FFFF, 
except for addresses $DDDO to $DFFF which contain the character 
generator ROM (Bank 14) or I/O chip registers (Bank 15). These are the 
easiest to use, especially Bank 15 with free access to I/O. The only 
limitation is the more limited access to RAM for your program. Since you 
still have over 12K of RAM to play with, that shouldn't be a major problem. 

On rare occasions you may find a need to tuck a program into high RAM. 
That makes the job harder. You will certainly be located beneath ROM, 
and that means you need to call to make bank transfers as your program 
calls the Kernal and returns. It can be done. But it is messier, and if you 
can relocate your program to eliminate the problem, do so. 



APPENDIX B — COMMODORE 128 



765 



Data in Other Banks (128) 

Wherever your program ends up, you may find a need to reference data 
in other banl<s— to load it, store it, or compare it. Three Kernal subroutines 
are available to help you do these actions. They are: 

Action Name Address 

Load INDFET $TT7A 

Store INDSTA $FF77 

Compare INDCMP $FF7fi 

All these use indirect, indexed addressing to reference the desired data. 
Thus, you must set up the indirect address in zero page as usual and load 
Y with the index value desired. You must give these subroutines two extra 
pieces of information: where the indirect address is located, and what data 
banl< is desired. 

The indirect address information is passed to the subroutine in one of 
several ways: 

For INDFET, load the address to register A; 

For INDSTA, put the address into location SDSBq; 

For INDCMP, put the address into location $DECfl. 

Indicate the desired bank (0 to 15) by loading its value into register X. 

It is wise to lock out interrupts with SEI before starting any of the above 
calling sequences; do not forget to release the interrupt with CLI after 
the call. Chapter 6 has an example of these routines. 

Jumping to Other Banks (0128) 

A JMP is slightly easier than a JS R, but neither is hard. The call addresses 
are: 

Action Name Address Alternate 

JMP JMPFAR $FF71 $DEE3 

JSE JSRFAR $FFE.E $DECD 

You must place the address of your desired destination into addresses E, 
3, and A . Oddly, the address is not "backwards" like most 650x addresses. 
The bank number goes into address E, the high address byte into 3, and 
the low byte into address A. Address 5 is a "status register" image, if you 
want it; usually it is best to leave this value as zero. If you want to pass 
information via the processor's registers, the values must be stored in 



766 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



memory: a at fc, X at 7, and Y at fl. Remember, you must set up addresses 
S to 4 before making the call. 

The same setup applies to both JMPFARandJSRFRR. About the al- 
ternate address: you cannot JMP or JSR to $FF71 or $FFtE /f frte 
ROM isn't there— m which case you must use the alternate address in 
low memory which is never switched. When you have everything set up, 
you may JMP to JMPFftR, since you will not need to come back. You 
must JSR to JSRFaR, and it's worth noting that this call will normally 
return to Bank 15 only. If you want to look at registers after the return, 
they will be saved in the locations noted above. 

The Screen (C128) 

The 40-column screen is mapped in the "usual" way. That is, whatever 
characters are stored in screen memory (usually $D4DDto$07E7) will 
be seen on the screen, and whatever appears on the nongraphics screen 
may be inspected at the corresponding point within memory. Material 
dealing with how to use the 64's video chip will normally be valid for the 
128. 

The 80-coiumn screen is driven in an entirely different manner. The char- 
acters on screen are mapped from memory — but not the computer's main 
memory. Instead, the video controller uses a "private" memory. We have 
to do a moderate amount of work to inspect or change this memory; a 
minimum of six commands are usually needed to reference a screen 
memory byte. For an illustration of the cumbersome method needed to 
do this, look at the character stored in the second position of the top row 
of the 80-column screen. The internal memory address of this character 
is □ DDI (high byte □, low byte 1); here we go. POKE 547fl4 , Ifl : POKE 
SA76A,D to set the high address byte. POKE 547fl< , iq : POKE 
SA7&A,l to set the low address byte. Finally, POKE 
5 4 7 a 4 , 3 1 : P R I N T PE E K ( 5 ^ 7 a 5 ) . We'll f inally get the character 
(in screen code, not ASCII) ... but that's a lot of work compared to a 
single PEEK on 40 columns. 

This system is not all bad. For one thing, blocks of "private" memory can 
be moved internally to provide for fast scrolling. For another, the 80-column 
controller has no need to dip into main memory to keep its screen alive; 
with the result that the 80-column machine can be much faster than the 
40-column one, which needs to reference memory almost continuously. 



c 



Memory 
Maps 

A word about memory maps: they are always too big or too small for the 
use you have in mind. 

The beginner may feel swamped by the wealth of detail. There's no threat, 
however. The information is there when you're ready for it. Browse through 
the information; it may be thought-provoking. Try reading or changing 
locations to see what happens. 

The advanced programmer may want more: lengthy details on how each 
location is used, which parts of the system use these locations, and so 
on. Time and space don't permit such detail. 

The maps are intended to be fairly complete. Those who want more detail 
may find them cryptic; but at least each location will be associated with a 
type of activity. Different machines may be compared by checking their 
respective maps. In some cases, programs may be converted with their 
use, since they will help to find the corresponding memory location in the 
target machine. 

When you see a reference to a POKE or PEEK location— in this book or 
from other sources — check it in these maps. They will help add perspec- 
tive. 



767 



768 MACHINE LANGUAGE FOR COMMODORE MACHINES 



"Original ROM" PET 

The Great Zero-Page Hunt 

Most users help themselves to the high part of the input buffer {$nQAU 
to $D05R, which is not used except when long lines of data are inputted. 

Most zero-page locations may be copied to another part of memory so 
that their original contents can be restored after use. However, the pro- 
grammer should take great care in modifying the following locations, which 
are critical within the operating system or BASIC: $D3, $05, $yA to 
$t7, $7ft to $fl7, $flq, $RE to $ft3, $B7, $C2 to $Dq, $£□ to $EE, 
$F5. 

Memory Map 



Hex 




Decimal 


Description 




■0002 


0- 




USE jump 


□ □03 




3 




Current I/O -prompt 










suppress 


□ □□5 




5 




Cursor control position 


□ □□fi- 


-oooq 


fl- 


■q 


Integer value (for SYS, GOTO, 










and so on) 


□□□a- 


-005R 


10- 


-aq 


Input buffer 


oosa 




qo 




Search character 


□ □5B 








Scan-between-quotes flag 


□ □5C 








Input buffer pointer; number of 










subscripts 


□ □5D 




q3 




Default DIM flag 


□ □5E 








Type: FF= string; 










00 = numeric 


□ □5F 








Type: 80 = integer; 00= floating 










point 


□oto 








Flag: DATA scan; LIST quote; 










memory 


OOtl 




^7 




Subscript flag; FNX flag 


□ OtE 




qfl 




□=INPUT; $^D=GET; 










$qfl=REaD 


□ 0t3 




qq 




aTN sign/comparison 










evaluation flag 


D0t4 




100 




Input flag (suppress output) 


OObB- 


-0Dt7 


101- 


-103 


Pointers for descriptor stack 



APPENDIX C — "ORIGINAL ROM" PET 



769 



Hex 




Decimal 


Description 


□ □tfl- 


□ □7D 


lOA 


-HE 


Descriptor stack (temporary 










strings) 


□ □71- 


□ □7^ 


113 


-lit 


Utility pointer area 


□ □75- 


□ □7fl 


117 


-lE^ 


Product area for multiplication 


□ □7ft- 


□ □7B 


152 


-1E3 


Pointer: start-of-BASIC 


□ □7C- 


□ D7D 


1E< 


-1E5 


Pointer: start-of-variables 


D07E- 


□ D7F 


lEfc 


-1E7 


Pointer: start-of-arrays 


□□ao- 


□ □fll 


lEfl 


-lER 


Pointer: end-of-arrays 


□ □flE- 


□ □fl3 


13^ 


-131 


Pointer: string-storage (moving 










down) 


DU&A- 


□□as 


13E 


-133 


Utility string pointer 


□ □flb- 


□ □fl7 


13^ 


-135 


Pointer: iimit-of-memory 


□ □flfl- 


□ □flq 


13t 


-137 


Current BASIC line number 


□ □flft- 


□ □flB 


13fl 


-13^1 


Previous BASIC line number 


□ □flC- 


□ DflD 


lAU 


-lAl 


Pointer:BASIC statement for 










CONT 


□ □flE- 


□ OflF 


IAS 


-1^3 


Current DftTA line number 


□ □RD- 


□oni 


lAA 


-IAS 


Current DftTR address 


□ □■=15- 


□ 0R3 


lAk 


-IA7 


Input vector 


□ □R<- 


□ □^5 


1A& 


-lAR 


Current variable name 


□ □Rb- 


□ □^7 


15^ 


-151 


Current variable address 


□ □Rfl- 


□□qq 


15E 


-153 


Variable pointer for FOR/NEXT 


□ □Rft- 


□ □•=16 


ISA 


-155 


Y-save; op-save; BASIC 










pointer save 


□ □RC 




15t 




Comparison symbol 










accumulator 


□ □HD- 


□ □ftE 


157 


-IbE 


Miscellaneous worl< area, 










pointers, and so on 


□ □aa- 


□ □ft5 


lt3 


-lti5 


Jump vector for functions 


□ □Rfc- 


□ □AF 


Itt 


-175 


Miscellaneous numeric work 










area 


□ □BQ 




17t 




Accum#1 : exponent 


□ □Bl- 


□ □B-^ 


177 


-IfiD 


Accum#1 : mantissa 


□ □B5 




lai 




Accum#1 :sign 


□ □Bt 




IflE 




Series evaluation constant 










pointer 


□ □B7 




lfi3 




Accum#1 hi-order (overflow) 


□ □Bfl- 


□ □BD 


Ifl^ 


-laq 


Accum#2: exponent, and so on 


□ □BE 




IRQ 




Sign comparison, Acc#1 versus 










#2 


□ DBF 




IRl 




Accum#1 lo-order (rounding) 



170 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 




Decimal 


Description 


n n o n 
□ □cu- 


n n r» 1 
UUL Ji 




1 n 3 


r^oocatto Hi iffor lonnth/QOriPQ 
Odoocllc UUiici lof ly u i/oci ICO 










poinicr 


rl n !3 


n n "n Q 




3 1 "7 


PHRfZPT CI iHrni itin^' npt 










DMOIw v/lidlCIUld 




n nr" n 

U uL,il 


3 n 1 


3 n 3 
•dud 


RAmO nnintpr fwithin 

D/^WIVy L/UII ltd ^VVIll III 1 










CI ihmi itinp^ 


n n T\ 
□ UDA- 




D 1 A 

c Jju- 


3 3 3 

■ddd 


DanHAm niimhpr qppH 

riOllvJUllI IIUIIIUCI 


n riT^ n 
□ Ut U- 


n ni? 1 
-UUti Jj 


— — - 


— I — If— 
-Ed5 


Pnintor trt cr^rppn linP 
rUIMLwl i\J Owl coll III IC 


□ DEE 




ddh 




D/\oitinn f\4 it'e/^r f\n Qk\m/A lino 

rOoiiion OT cursor on auuvc iiiic 


UUhd- 




dd r- 


3 3 A 

-ddO 


1 ltilit\/ nnintpr* tsnp cprnll 
^iiiiiy |JUiiiLd< ia\jxSf ouivjii 


n m? c 


-UU£ib 


— 1 — 1 n 


3 3 n 
-ddU 


Tano pnH flHHrPcc/pnrI nf 

1 dUC? Cl lU dUUI COO/\71 lU KJl 










curr6ni progrdiii 


UUii r - 


-U U£i □ 


d31- 


3 3 3 

-ddd 


Tanp timinn pnnctantc 

1 atJC? iiiiiiiiM loicii lio 










1 ap6 UUTTci CndrdOLci 


□ □£A 








LJiroOL/|jiuyidiiiiiicu uuioui. 










U — UliCLfL 


n n "CI o 

□ □EB 




3 c 




Tana rpaH timor 1 pnahlpH 
1 d|Jc/ icdU III MCI 1 CI iduicu 










POT rpopiv/pH frnm tanp 
u^v^ 1 1 coci vcu 1 1 \ji 1 1 


□ □ED 




537 




ncdU oiididoiCi cnui 


n n "CI T3 

□ □EE 




3 '3 A 
C 3 □ 




iNurnucr oi uiidrdoicio iii iiic 










namp 

1 Idll IC 


n n "CI xi 

□ □Er 




3 '3 □ 




wUiicilL illc lUyiOdi dUUICoo 


n m? n 




3 /■ n 
U 




r^iirrpnt filp ^^c-nndfirM f)HrlrpQC 

ouiiciii IIIC ocwWi lucii y auui coo 


n n 1? "1 








r^i irront fMp Hp\/ir^P niimHpr 

OUllClll Illc UCVIUC llUillUCI 


n n xi ^ 

□ □Ed 




3 /■ 3 




Line mdryin 


n mr'3 


-UUr 'I 




-EAA 


Pointpr* ctart nf tanp huffpr 

r wii iici • oicii I v^i ici|^c uuiici 


□ □F5 








Line where cursor lives 


□ □Ft 




3 /■ L 
dH b 




Last l<ey/checl<sum/ 










nnic^dtanpm ic 
illlouclldl icUUo 


□ □rr- 


-UUro 


3 X "5 

d^ r- 


3 ^ A 
-CM Q 


1 ape Slail aauicSS 


ULI f H- 


-uur ft 


3 /■ a 


3 c n 


Pila noma nnintor 

nic ndiTiu puiiUci 


UUr D 




3 C 1 

dbil 




Miimhpr nf TNc:7PTc 
iNuriiUci ui XLNoricxo 










ni itctanHinn 
uuioidi luii ly 


UUc L 








\A/rita cHift \A/nrH/rpaH oHarantor 
VVillc oiliil wuiU/icdU uiididuici 


ODFD 




553 




in 

Tape blocl<s remaining to write/ 










read 


□ GFE 








Serial word buffer 


□ !□□• 


-□IDft 


E5b 


-Ett 


STE$ work area 


□ 


-□13E 


E5t 


-31fl 


Tape read error log 


□ !□□ 


-□IFF 


E5b 


-511 


Processor stacl< 



APPENDIX C — "ORIGINAL ROM" PET 



171 



Hex 




Decimal 


Description 


□ 200- 

LJ L. I_l LJ 


.npnp 

LJ ^ LJ ^ 


biic- 


-bid 


jury ciocK Tor x ± ana i j. * 


U C U J 




515 




wnicn Key aown. ebb = no K6y 


U C U H 




bib 




onin Key. i it aepressed 


n?rm- 

U C LI 


U C U D 


3 Jj r - 


CIA 

-d Jj o 


v/orreciion ciock 


DED7- 


LJ l_ LJ LJ 


CIO 


c 3 n 


oassciie siaius, flfjj ana ifc 


Ll L_ LJ 1 




5E1 




ixeyswiicn ciR. oivc ana 










RVS flags 


□ EDA 




bcc 




Timing constant for tape 


u c u o 




C D "3 

bed 




Loaa = u, verity = i 


U t_ LJ V_> 




c 3 /■ 
b c'l 




OlalUS WOru o 1 


□ POD 

LJ L- LJ U 




CPC 

-] C P 




iNurnuer oi criaraciers in 










Uoi/Kna rH Kiiffar 
l\cyUUcliU UUIfci 


□ 2QE 




C P L 
P C b 




oorccii reverse riay 


□ 20F- 


LJ l_ ^ Ul 


be r- 


c 3 r 
■bd b 


rxeyuuarci inpui uurrer 


□ 2iq_ 


LJ i_ jj n 


bd r- 


Q 

■bdo 


± £v veclur 


npi.R- 

U C JJ o 


U C Ji L« 


c n a 
bdT- 


c /" n 
■b A U 


Unix interrupt vector 


npl.n 

U C JJ L/ 




c y 1 
b^ 1 




■etc output, c b b = cnaracter 










penoing 


U C JJ Ij 




c /* □ 
bs c 




Cn^.nf lino fm* inm it i^/^in'f^v 

cna-oT-une-Tor-inpui pointer 


nppri- 

u c c u 


-flPPI. 

U C C JJ 




eye 
•b^b 


L/Ursor log ^row, coiunnn) 


nppp 

u c c c 




b A b 




icct output Dutter 


U C C J 




b'l 7 




f\ey image 






C /* A 

b'l Q 




u — tiasn cursor 


U C C 3 




C /* Q 

bH "i 




oursor liming couniaown 


nppL 

u c c tl 




CCD 
P p u 




onciracier unaer cursor 


□ P27 




C C 1 

b b 1 




ouioUi III uiiiiiv pi ictoe 


U C C G 




c C J 
b d c 




ri u 1 receivea irom tape 


U l_ ^ 1 


LJ ^ *-f JJ 


c c *□ 
bbd — 


C "7 "7 

■b r r 


Q/^roon lino \A/ron fraHIa 

ooreeii iiiie wrap lauie 


npz; p_ 

LJ L *-l t 


U C H IJ 


C "7 A 

b r □ — 


C A-7 
bo r 


me lugiuai aourebs lauie 


LJ L. *-1 


LJ L^ J 


C A A 

b Q — 


e a "7 

•bn f 


■ lie ueviue iiuiiiuei lauie 


u c ^ □ 


u c D r 


CCA 


(L n "7 
bU r 


me secondary auoress laoie 


u c □ u 




L n A 

b U u 




Inm it fminn o/^fAAn/fmin 

inpul irom soreen/irom 












QEkl 








X save 










IHow many open files 


□ Et3 




til 




Input device, normally □ 


□ Et4 




fclE 




Output CMD device, normally 3 


□ Eb5 




tl3 




Tape character parity 


□ Ett 




tl4 




Byte-received flag 


□ Etfl- 


□ EbR 


fcl5- 




File name pointer; counter 



772 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 



Decimal 



Description 



□ EtF 
DE7D 

□ 273 
DE75 

□57t-D277 
D57fl 



□ 27q 

□ 27R- 

□ 33a- 

□ 3FA- 

□ ^DD- 

flDDO- 
CODD- 



-□33q 
-□3Fq 
-□3FB 
-7FFF 

-fl3E7 
-E7Ffl 



t53 
tE7 

b3D-t31 
b3E 

t33 

t34-fl25 
flab-lD17 
IDlfl-lDlR 
1054-3E7fc7 

3E7tfl-337b7 
^qi5E-5q3fl< 



EfllD-Eai3 ER^Dfl-Sq^ll 

EflE^-Efl53 5S4E^-5R4E7 
Efl^D-Efl^F 5^-^5^-5^471 

FDDD-FFFF fcl44D-t5535 



Serial bit count 

Cycle counter 

Tape writer countdown 

Tape buffer pointers, #1 and 

#E 

Write leader count; read pass 
1/2 

Write new byte; read error flag 
Write start bit; read bit 
sequence error 
Error log pointers, pass 1/2 
□ = scan/1-1 5 = count/ 
$4^ = load/$aD=end 
Write leader lengtfi; read 
checksum 

Tape#l input buffer 
Tape#E input buffer 
Monitor extension vector 
Available RAM including 
expansion 

Screen RAM memory 
BASIC ROM; part of kernal 
ROM 

PI A 1 (6520)-keyboard 
interface 

PIA E (6520)-iEEE interface 
VIA (6522)-Miscellaneous 
interface, timers 
Kernal ROM routines. 



PIA and VIA charts are the same as shown for Upgrade/4.0 units. 



UPGRADE and BASIC 4.0 Systems 

Tlie Great Zero-Page Hunt 

Zero-page locations are tough to find in these areas. Locations $1F to 
$E7, $<Bto $5^, and $54 to $5D are work areas available for tem- 
porary use. If tape is not being read or written, addresses $B1 to $C3 
are available. 



APPENDIX C — UPGRADE AND BASIC 4.0 SYSTEMS 



173 



Most zero-page locations may be copied to anotlier part of memory so 
that their original contents can be restored after use. The programmer 
should take great care, however, in modifying the following locations, which 
are critical within the operating system of BASIC: $10, $13 to $15, 
$Eato$3 5, $37, $5Dto$51, $E.5, $7Dto$fl7, $flDto$BD, $CA 
to $FR. 

Memory Map 

Where Upgrade ROM differs from 4.0, an asterisk (*) is shown and the 4.0 
value is given. There are some differences in usage between the 40- and 
80-column machines. 



Hex 




Decimal 


uescripuon 


□ □□0- 


-□□□E 


0- 


-E 


USE jump 


□ □□3 




3 




Search character 










Scan-between-quotes flag 


0DD5 




5 




Input buffer pointer; number of 










subscripts 


□ □□t 








Default DIM flag 


00D7 




7 




Type: FF = string; □□ = numeric 


□ □□fi 




a 




Type: flO = integer; 










00 = floating point 


□ □□S 








Flag: DRTfl scan; LIST quote; 










memory 


□ □□A 




10 




Subscript flag; FNX flag 


□ □OB 




11 




D=INPUT; $40=GET; 










$qfl=REaD 


OODC 




IE 




ATN sign/comparison 










evaluation flag 


□ □OD- 


■□□OF 


13- 


■15 


"Disk status DS$ descriptor 


□ DID 




It 




*Current I/O device for prompt- 










suppress 


DOll- 


■□□IE 


17- 


■Ifl 


Integer value (for SYS, GOTO, 










and so on) 


□ □13- 


•0015 


iq- 


■El 


Pointers for descriptor stack 


□ □It- 


•OOIE 


EE- 


■3D 


Descriptor stack (temporary 










strings) 


□ □IF- 


•OOEE 


31- 


■3A 


Utility pointer area 


□ □53- 


■00E7 


35- 


■3q 


Product area for multiplication 


□ □Efl- 


■OOEq 


^0- 


•41 


Pointer: start-of-BASIC 


□□aa- 


ODEB 


4E- 


■A3 


Pointer: start-of-variables 


□ □EC- 


OOED 




■AS 


Pointer: start-of-arrays 



174 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 




Decimal 


Description 


□ □EE- 


□ □EF 


Af=- 


47 


Pointer: end-of-arrays 


□ □3D- 


□ □31 


A&- 


4q 


Pointer: string-storage (moving 










down) 


□ □3a- 


□ □33 


50- 


51 


Utility string pointer 


□ □34- 


□ □35 


5E- 


53 


Pointer: limit-of-memory 


□ □3b- 


■□□37 


54- 


55 


Current BASIC line number 


□ □3fl- 


■□□3q 


5b- 


-57 


Previous BASIC line number 


□□3a- 


-□□3B 


5fl- 


-5q 


Pointer: BASIC statement for 










CONT 


□ □3C- 


-□□3D 


fcO- 


-bl 


Current DRTfi line number 


□ □3E- 


-□□3F 


fcE- 


-b3 


Current DATA address 


□ □<□- 


-DQAl 


b4- 


-b5 


Input vector 




-□□43 


bb- 


-b7 


Current variable name 


nuAh- 


■QUA7 


7^- 


-71 


Variable pointer for FOR/NEXT 




-□□4H 


7E- 


-73 


Y-save; op -save; BASIC 










pointer save 


UQAk 




74 




Comparison symbol 










accumulator 


QQAB- 


-□□5^ 


75- 


-flD 


Miscellaneous work area, 










pointers, and so on 


□ □51- 


-□□53 


fil- 


-fl3 


Jump vector for functions 


□ □5-^- 


-□□5D 


fl4- 


-=13 


Miscellaneous numehc work 










area 


□ □5E 




q4 




Accum#1 : exponent 


□ □5F- 


-□□tE 


q5- 


-qa 


Accum#1 : mantissa 


□ □fc3 








Accum#1 : sign 


QULA 




1^^ 




Series evaluation constant 










pointer 


□ □b5 




1^1 




Accum#1 hi-order (overflow) 


□ Otb- 


-□□tB 


l^E- 


-1D7 


Accum#2: exponent, and so on 


□□tc 




l^fl 




Sign comparison, Acc#1 versus 










#2 


□ OtD 




l^b 




Accum#1 lo-order (rounding) 


□ □tE- 


-□□tF 


ll^- 


-111 


Cassette buffer length/series 










pointer 


□ □?□■ 


-□□fl7 


llE 


-135 


CHRGET subroutine; get 










BASIC character 


□ □77 


-□□7a 


IIR 


-la^ 


BASIC pointer (within 










subroutine) 


□ □fifl 


-□□flC 


13b 


-14D 


Random number seed 


□ □flD 


-□□flF 


141 


-143 


Jiffy clock for TI and TI$ 



APPENDIX C — UPGRADE AND BASIC 4.0 SYSTEMS 



175 



Hex 




Decimal 


Description 


□oqo- 


■□□qi 


lAA- 


■IAS 


IRQ vector 




■□□q3 




■1A7 


BRK interrupt vector 


□oq^- 


■□□qs 




■i^q 


NMI interrupt vector 


□□qt 




15^ 




Status word ST 


□ □q? 




151 




Wliicli key down: 25 5 = no key 


□□qa 




155 




Sliift key: 1 if depressed 


□□qq- 


□oqa 


153- 


■ISA 


Correction clock 


□□qB 




155 




Keyswitch PI a: STOP and 
RVS flags 


□oqc 




15t 




Timing constant for tape 


ooqD 




157 




Load = D; verify =1 


□□qE 




15fl 




Number of characters in 
keyboard buffer 


□ □qp 




15q 




Screen reverse flag 


□□ao 




ItQ 




IEEE output: E55 = character 
pending 


□ OAl 




Itl 




End-of-line-for-input pointer 


□ □R3- 




lt3- 


11.A 


Cursor log (row, column) 


ooas 




lt5 




IEEE output buffer 






Itt 




Key image 


□□a? 




It? 




□ = flash cursor 


□ □ftfl 




Ibfl 




Cursor timing countdown 


□□aq 




iE,q 




Character under cursor 


□□aa 




17^ 




Cursor in blink phase 


□ □aB 




171 




EOT received from tape 


□ □ac 




173 




Input from screen/from 
keyboard 


□ □aD 




173 




X save 


DoaE 




17^ 




How many open files 


ooaF 




175 




Input device, normally □ 


□ OBQ 




l?b 




Output CMD device, normally 3 


DDBl 




177 




Tape character parity 


□ □BE 




17fl 




Byte-received flag 


□ □B3 




i7q 




Logical address temporary save 


UUBA 




la^ 




Tape buffer character; MLM 
command 


□ □B5 




lai 




File name pointer; MLM flag; 
counter 


□ □B7 




ia3 




Serial bit count 


□□Bq 




IflS 




Cycle counter 


□ □Ba 




lat 




Tape writer countdown 



776 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 




Decimal 


Description 


□ QBB- 


□ □BC 


lfl7- 


Iflfl 


Tape buffer pointers, #1 and 










#E 


□ □BD 




laq 




Write leader count; read pass 










1/2 


□ QBE 








Write new byte; read error flag 


□ DBF 








Write start bit; read bit 










sequence error 


OOCD- 


□ □CI 


IRE- 


1R3 


Error log pointers, pass 1/2 


□ □C2 








□ = scan/1 - 15 = count/ 








$^^ = load/$fl^ = end 


□ QC3 




1R5 




Write leader length; read 










checksum 


UUCA- 


□ □C5 


IRt- 


•1R7 


Pointer to screen line 


QDCb 








Position of cursor on above line 


unci- 

LJ LJ 1 


■□□Cfl 




-E^D 


Utility pointer: tape, scroll 


ODCR- 


-□□CA 


l_ LJ -U 


-E^E 


Tape end address/end of 










current program 


□ QCB- 

LJ LJ v_« LJ 


-□□CC 


EU3- 


-E^4 


Tape timing constants 


nocD 

Ul LJ Vrf !>/ 




ED5 




□ = direct cursor; else 










programmed 


□ OCE 




^□ti 




Tape read timer 1 enabled 


□ □CF 




^□7 




EOT received from tape 


ODDD 




EDfl 




Read character error 


□ ODl 




^□'l 




Number of characters in file 










name 


□ DDE 




EID 




Current file logical address 


□ □D3 




Ell 




Current file secondary address 


QUDA 




ElE 




Current file device number 


□ □D5 




E13 




Right-hand window or line 










margin 


□ DDt- 


-□□D7 


E14- 


-E15 


Pointer: start of tape buffer 


ODDfl 




Elt 




Line'where cursor lives 






E17 




Last key/checksum/ 










miscellaneous 


□□Da 


-□□DB 


Elfl 


-EIR 


File name pointer 


□ □DC 




EE^ 




Number of INSERTS 










outstanding 


□ □DD 




EEl 




Write shift word/read character 


□ □DE 




EEE 




in 

Tape blocks remaining to write/ 



read 



APPENDIX C — UPGRADE AND BASIC 4.0 SYSTEMS 



t77 



Hex 




Decimal 


n n T> "0 

□ □DF 




SE3 




□ □ED- 


□ □Ffl 




-EAQ 


□ □ED- 


□ □El 


EE4- 


-EES 


□ □ES 




EEb 




□ □E3 




EE7 




□ □E< 




EEfl 




□ □E5 




P P Q 




n n "CI r 




E3^ 




DQE7 




E31 




□ □Efl 




E3E 




OOEq- 


□ □Eft 


E33- 


-E3^ 


□ OEB- 


□ □EC 


E35- 


-E3t 


ODFS- 


□ □FR 




-E5^ 


□ □FB- 


□ □FC 


E51- 


-E5E 


□ □FD- 


□ □FE 


E53 


-ESA 


□ lOD- 


□ l^ft 


E5t 


-Efct 


OlDD- 


□ 13E 


E5t 


-31fl 


□ 


□ IFF 


E5t 


-511 


QEQD- 


□ E5D 


51E 


-BRE 


□ E51- 


-□E5ft 


5^3 


-^□E 


□ E5B- 


■nEhA 


bD3 


-tlE 


□ Eb5- 


•□EbE 


bl3 


-tEE 


□ EtF- 


■□S7fl 


bE3 


-fc3E 


0E7R- 


-□33q 


t3< 


-flE5 


033a- 


■□3Fq 


fiEt 


-1^17 


Q33ft- 


■□3fi^ 


fiEt 




03Eq 




!□□! 




03Ea 




l^^E 




03EB 




1^^3 




□ 3EC 




inuA 




□ 3ED 








03EE 




IDDb 




03EE- 


■□3F7 




-1D15 


□ 3EF 




1^D7 




□ 3FD- 




l^Dfi 


-1D17 


Q3Fa- 


□ 3FB 


l^lfl 


-i^iq 



Description 



Serial word buffer 
(40-column) Screen line wrap 
table 

*(80-column) Top, bottom of 
window 

*(80-column) Left window 
margin 

*(80-column) Limit of keyboard 
buffer 

*(80-column) Key repeat flag 
*(80-co!umn) Repeat countdown 
*(80-column) New key marker 
*(80-column) Chime time 
*{80-column) HOME count 
*(80-column) Input vector 
*(80-column) Output vector 
Cassette status, #1 and #E 
MLM pointer/tape start address 
MLM, DOS pointer, 
miscellaneous 

STR$ work area, MLM work 
Tape read error log 
Processor stack 
MLM work area; input buffer 
File logical address table 
File device number table 
File secondary address table 
Keyboard input buffer 
Tape#l input buffer 
Tape#E input buffer 
*DOS work area 
(Fat 40) New key marker 
(Fat 40) Key repeat countdown 
(Fat 40) Keyboard buffer limit 
(Fat 40) Chime time 
(Fat 40) Decisecond timer 
(Fat 40) Key repeat flag 
(80-column) Tab stop table 
(Fat 40) Tab work value 
(Fat 40) Tab stops 
Monitor extension vector 



778 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex Decimal 



□3FC 

04DD-7FFF in2A-327h7 

flDDD-a3E7 3E7tfi-337fc7 
flDDD-fi7CF 3E7t,a-3^7L7 
qaOD-aFFF 3bfit<-^5D55 
BDDD-E7FF ^5D5t.-5q3Rl 
Efll0-Efll3 BH^Dfl-SR^ll 
EflEn-Efl53 5q'^E4-5R^27 
Efl^D-Efl^F 5R45fc-5q^71 
EflflD-Eflfll BSBED-B^SEl 

FDDO-FFFF tl4<D-t.5535 



Description 

*IEEE timeout defeat 
Available RAM including 
expansion 

(40-column) Video RRM 
*(80-column) Video RAM 
Available ROM expansion area 
BASIC ROM, part of kernal 
PI A l-l<eyboard I/O 
PI A E-IEEE-488 I/O 
VIA-l/0 and timers 
(80-column and Fat 40) CRT 
controller 
Kernal ROM 



6520 



E810 


Diag Sens/ 
Uncrash 


EOl in 


Tape Switch Sense 
#1 #2 


Keytjoard Row Select 


59408 


E811 


Tape#1 In 
Latch 




(Screen Blank— Orig 
ROM) EOl Out 


DDRA 
Access 


Tape#1 Input L 
Control 


59409 


E812 


Keyboard Input for selected row 


59410 


E813 


Retrace 
Latch 




Cassette#1 Motor 
Output 


DDRB 
Access 


Retrace Interrupt 
Control 


59411 



Figure C.I 
PIA 1 chart 



6520 



E820 


IEEE-488 Input 


59424 


E821 


ATN Int 




NDAC Out 


DDRA 
Access 


ATN Int Control 


59425 


E822 


IEEE-488 Output 


59426 


E823 


SRQ Int 




DAV Out 


DDRB 
Access 


SQR Int Control 


59427 



Hgure C.2 
PIA 2 chart 



APPENDIX C — CBM 8032 AND FAT-40 



179 



6522 









Retrace 
In 


Tape#2 
Motor 


Tape 
Output 






NRFD 
Out 






E840 


DAVIn 


NRFD In 


ATN Out 


NDAC In 


59456 


E841 


Unused (See E84F) 


59457 


E842 






Data Direction Re 


g 


ster B (for E840) 








59458 


E843 






Data Direction Re 


g 


ster A (for E84F) 








59459 


E844 
E845 








Timer 1 












59460 
59461 


E846 








Timer 1 Latch 












59462 
59463 


E848 
E849 


Timer 2 


59464 
59465 


E84A 


Shift Register (unused) 


59466 


E84B 


T1 Control 


T2Cont 


Shift Register Control 


Latch Controls 
PB PA 


59467 


E84C 


CB2 (PUP) Control 


CB1 CntI 

Tape#2 


CA2 Control 

GraphicsAText Mode 


CA1 

(PUP) 
Control 


59468 


E84D 
E84E 


Irq Stats 
Int EnabI 


Timer 
1 

Int 


Timer 
2 
Int 


CB1 
Tape#2 
Int 


CB2 
(PUB) 
Int 


SR 
Unused 


CA1 
(PUP) 
Int 


CA2 
G/T Mode 
unused. . 


59469 
59470 


E846F 






Parallel User Port Data Re( 


y 


ster PA 








59471 



Figure C.3 
VIA chart 



CBM 8032 and FAT-40 
6545 CRT Controller 

NOTES: 1 . Registers are write-only. 

2. Avoid extreme changes in Register 0. CRT damage could 
result. 

3. Register vi/ill adjust scan to allow interfacing to external 
monitor. 

4. Register 12, Bit 4, will "invert" the video signal. 

5. Register 12, Bit 5, switches to an alternate character set. The 
character set is not implemented on most machines except 
Super-PET. 



780 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



$E880 
59520 



$E881 TYPICAL VALUES 

59521 (DECIMAL) 

i TEXT GRAPHICS 






HORIZONTAL TOTAL 


1 


HOR. CHAR. DISPLAYED 


2 


H. SYNC POSITION 


3 


V SYNC WIDTH h 


4 


X VERTICAL TOTAL 


5 




VERT. TOT. ADJUST 


6 




VERTICAL DISPLAYED 


7 




VERT. SYNC POSITION 


8 




MODE 


9 


SCAN LINES 


10 




CURSOR START (UNUSED) — 


11 


— ( 


12 


X 


C 


R DISPLAY 


13 


ADDRESS 



49 
40 
41 
15 
32 
3 
25 
29 

9 


16 




49 
40 
41 
15 
40 
5 
25 
33 

7 


16 




NOTES: 1. REGISTERS ARE WRITE-ONLY 

2. AVOID EXTREME CHANGES IN 
REGISTER, OR CRT DAMAGE 
COULD RESULT 

3. REGISTER WILL ADJUST SCAN 
TO ALLOW INTERFACING TO 
EXTERNAL MONITOR 

4. REGISTER 12, BIT 4, WILL "INVERT" 
THE VIDEO SIGNAL. 

5. REGISTER 1 2, BIT 5, SWITCHES TO 
AN ALTERNATE CHARACTER SET. 
THE CHARACTER SET IS NOT 
IMPLEMENTED ON MOST MACHINES 
EXCEPT SUPER-PET. 

Figure C.4 



APPENDIX C — VIC 20 



181 



VIC-20 

The Great Zero-Page Hunt 

Locations $FC to $FF are available. Locations $52 to $^E to 
$53, and $5? to $tD are work areas available for temporary use. 

Most zero-page locations may be copied to another part of memory so 
that their original contents can be restored after use. However, the pro- 
grammer should take great care in modifying the following locations, which 
are critical within the operating system or BASIC: $1B, $lt to $lfi, 
$2Bto $3a, $3a, $53 to $54, $ta, $73 to $flA, $qDto $Rft, $aD 
to $ftE, $Ba to $Bft, $C5 to $YA. 

Memory Map 







Dpoimsl 


Descriotion 


ODDD- 


•□□□2 




USR jump 


□ Q03- 


■DQQA 


3-4 


Float-fixed vector 


□ □05- 


■OODh 


5-t 


Fixed-float vector 


□ □□? 




7 


Search character 


□□□a 




a 


Scan-quotes flag 


□ □□q 




q 


TfiB column save 


□ □□A 




10 


D = LOaD, 1 = VERIFY 


□ □□B 




11 


Input buffer pointer/number of 
subscripts 


□ □□C 




12 


Default DIM flag 


□ □□D 




13 


Type: FF = string; 00 = numeric 


□ □OE 




14 


Type: a = integer; 
O0=floating point 


□ □OF 




15 


DATA scan/LIST quote/ 
memory flag 


OOID 




It 


Subscript/FNx flag 


0011 




17 


D=INPUT; $4D=GET; 
$qa=REftD 


ooie 




la 


ATN sign/Comparison 
evaluation flag 


□ □13 




iq 


Current I/O prompt flag 


□ 014- 


-□□15 


EO-El 


Integer value 


OOlt 




EE 


Pointer: temporary string stack 


□ □17- 


-□oia 


E3-E4 


Last temporary string vector 



182 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 




Decimal 


Description 


U LJ JJ n 


□ □31 




pp 


Stack for temporary strings 


nn??- 

u u c ^ 


□ 035 

LJ LJ l_ _J 


J H — 


P7 
J r 


Utility pointer area 


U U C D 


U U C £l 


p □ — 


Z P 


Product area for multiDlication 


nnPR_ 

UUCD — 


nnpr 
u u c ^ 


'i P — 




Pointer- start-of-BASIC 


n n pr» 


U U C£i 


'I P — 


Z L 


Polnfpr' ^tart-of-variables 


uucr — 


n rr^ n 


r — 


Z A 


Pnintpr* ^tart-of-arravs 


nmi. 

U U J Ji — 




Z Q_ 


P u 


Pointpr' end-of-arravs 

r wii iivi ■ wi lu WI Mi 1 uy w 






j jj 


CP 


Pointer* strino-storaoe fmovina 

1 Wii i Iwi ■ wll II ijg W WI V 111 I w VII 










down) 


UUIj j 






-t;4 


Utiiitv strina Dointer 

^^IIIILV Wll II M\A MWll IWI 


U U J f 


.nrr^ ft 


p p 


D □ 


Pointer* limit-of-memorv 

1 ^/ll l^^^l ■ llllllfe \#l 1 1 l\^l I V 


U U J " — 


.n m B 

'U UP n 




^ u 


Ciirrpnt BASIC line number 

1 1 wl 1 1 LJt\^Jt\^ III 1 w 1 IVII 1 ll<^ wl 






D — 


-t,n 


Previous BASIC line number 

1 1 V I^^U W 1 III ■ 1 Ml 1 Ih^^^l 


UU J LI 




a Jj 


□ ^ 


Pointer: BASIC statement for 










CONT 


DD3F- 


■□□4D 




t4 


Current DATA line number 


□ □41- 


■□□42 


t5- 




Current D&TA address 


nnA3- 


□ □44 


b7- 




Input vector 


□ □45- 


■□□4t 


EjR- 


•7D 


Current variable name 


□ □47- 


-□□4fl 


71- 


■7E 


Current variable address 


□ □4R- 


■□□4R 


73- 


■74 


Variable pointer for FOR/NEXT 


□ □4B- 


•□□4C 


75- 


■7t 


Y-save; op-save; BASIC 










pointer save 


□ □4D 




77 




Comparison symbol 










accumulator 


□ □4E- 


■□□53 


7fl- 


■fl3 


Miscellaneous work area 

IVIiW\^WIIUI IWWUW VWI Ix Vtl Wwi) 










Dointers and so on 


□ □54- 


-□□5b 


A4- 

l_J *1 


U □ 


Jumo vector for functions 

UUI 1 ill/ V WwVWI 1 WI i Ul i w&i Wi i w 


□ □57- 




fl7- 




Miscellanenufi numeric work 

iViiOW^OiiCli iwWUw 1 iUI 1 Iwl Iw VVWl l\ 










area 


□ □bl 




^7 




Accum#li' exDonent 


□ □tE- 


-□□fc5 


Sfl- 


-IDl 


Accum#l: mantissa 


□ □bb 




l^E 




Accum#l: sign 


□ □fc7 




1^3 




Series evaluation constant 










pointer 


□ □tfi 




1^4 




Accum#1 hi-order (overflow) 


□□tq- 


-□□tE 


1^5- 


-ll^ 


Accum#2: exponent, and so on 


□ □tF 




111 




Sign comparison, Acc#l versus 










#E 


□ □7D 




112 




Accum#l lo-order (rounding) 



APPENDIX C — VIC 20 



183 



Hex 




Decimal 


Description 


□ 071- 


-□□72 


113- 


-IK 


Cassette buffer length/series 
pointer 


□ D73- 


-□□aa 


115- 


-13a 


CHRGET subroutine; get 
BASIC character 


□ □?&■ 


-□□7B 


15E- 


-1E3 


BASIC pointer (within 
subroutine) 


□ □SB- 


-□□aF 


13q- 


-1A3 


END seed value 


□ □SO 








Status word ST 


DOHl 




IAS 




Keyswitch PI a: STOP and 
EVS flags 


n n n — 1 








Timing constant for tape 


□ □R3 




1A7 




Load = D; verify =1 


n n n /■ 




iAe> 




Serial output: deferred character 


00H5 








flag 








Serial deferred character 






ISD 




Tape EOT received 


□ □s? 




151 




Register save 


□ □sa 




155 




How many open files 






153 




Input device, normally □ 


□ORa 




154 




Output CMD device, normally 3 


OOHB 




155 




Tape character parity 


ODRC 




15t 




Byte-received flag 


OORD 




157 




Direct = $ a □/RUN = □ output 
control 


n PI mn 

□ □HE 




15a 




Tape pass 1 error log/character 
buffer 


□ □RF 




15q 




Tape pass E error log corrected 


OOAD- 


-□□as 


ItD- 


-ItE 


Jiffy Clock HML 


□ OAB 




lt.3 




Serial bit count/EOI flag 






lt4 




Cycle count 


n n 7\ c 




lb5 




Countdown, tape write/bit count 


□ □At 




ILt 




Tape buffer pointer 


□ □ft? 




lti7 




Tape write leader count/read 


□□aa 








pass/inbit 




ita 




Tape write new byte/read error/ 
inbit count 


□□as 




itq 




Write start bit/read bit error/stbit 


□□aa 




17^ 




Tape Scan;Cnt;Load;End/byte 


□□an 








assembly 




171 




Write lead length/read 
checksum/parity 



184 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex Decimal Description 



□□ac- 


□ □AD 


17E- 


173 


Pointer: tape buffer, scrolling 


□ □ftE- 


□ □fiF 


174- 


175 


Tape end address/end of 










program 


□ □BD- 


□ □Bl 


17t.- 


17? 


Tape timing constants 


□ □BE- 


□ □B3 


17fl- 


l?q 


Pointer: start of tape buffer 


DUBA 








1 =tape timer enabled; bit count 


□ □B5 




lai 




Tape E0T/RS232 next bit to 










send 


□ □Bt 




IflE 




Read character error/outbyte 










buffer 


DOB? 




lfl3 




Number of characters in file 










name 


□ □Bfi 




l&A 




Current logical file 


DOBq 




135 




Current secondary address 


□ □BR 




l&h 




Current device 


□ □BB- 


■□□BC 


lfl7- 


■Iflfl 


Pointer to file name 


□ DBD 




iflq 




Write shift word/read input 










char 


□ □BE 




mn 




Number of blocks remaining to 










write/read 


□ □BF 




iHi 




Serial word buffer 


□ OCO 




IRE 




Tape motor interlock 


□ OCl- 


-□□CE 


1^3- 


■iq< 


I/O start address 


□ □C3- 


■nucA 


IRS- 


-iqt 


Kernal setup pointer 


□ □C5 




1^7 




Last key pressed 


□act 




iqfl 




Number of characters in 










keyboard buffer 


□ DC? 




iqq 




Screen reverse flag 


ODCfi 




EDD 




End-of-line for input pointer 


oocq- 


-□□ca 


EDl- 


-EDE 


Input cursor log (row, column) 


□ □CB 




E^3 




Which key: kA if no key 


□occ 




BUA 




□ = flash cursor 


□ □CD 




BOS 




Cursor timing countdown 


□ □CE 




EDt 




Character under cursor 


□ □CF 




ED? 




Cursor in blink phase 


□ □D^ 




EDfi 




Input from screen/from 










keyboard 


□ □Dl- 


-□□DE 


EDq- 


-El^ 


Pointer to screen line 


□ □D3 




Ell 




Position of cursor on above line 



APPENDIX C — VIC 20 



185 



Hex 




Decimal 


Description 






ElE 




□ = direct cursor; else 
programmed 


□ DDE 




E13 




Current screen line length 


□ □Dt 




El< 




Row where cursor lives 


□ □D7 




S15 




Last inkey/checksum/buffer 


□ □Dfl 




Elt 




Number of INSERTS 
outstanding 


□ DDR- 


■□□F^ 


E17- 


E^^ 


Screen link table 


□ □Fl 




E^l 




Dummy screen link 


OGFE 




E4E 




Screen row marker 


D0F3- 


■QDF^ 


E<3- 


•E<< 


Screen color pointer 


□ 0F5- 


■□□Ffc 


E45- 


■E^t 


Keyboard pointer 


□ QF7- 


■□□Ffi 


E^7- 


■E^a 


RS-232 Rev pntr 


OOFq- 


■□□Fa 


E^q- 


E5D 


RS-232 Tx pntr 


□ □FF- 


■oina 


E5b- 


■Etfc 


Floating to ASCII work area 


□ 


^□3E 


E5t- 


•3ia 


Tape error log 


□ lOD- 


□ IFF 


E5t- 


•511 


Processor stack area 


□ 5Qa- 


□ EBfl 


51E- 




BASIC input buffer 


□ ESR- 


-□EtE 


^□1- 


-tl^ 


Logical file table 


□ Et3- 


■□Etc 


tll- 


-tE^ 


Device number table 


□ 2tD- 


-□E7fc 


tEl- 


-fc3^ 


Secondary address table 


□ 577- 


-□Efl^ 


t31- 


-yAU 


Keyboard buffer 


□ 561- 


-□EflE 


hAl- 


-t<E 


Start of BASIC memory 


□ 5fi3- 


-□Efl4 


t43- 




Top of BASIC memory 


□ EflS 




t45 




Serial bus timeout flag 


□eat 








Current color code 


□ Efl7 




t<7 




Color under cursor 


□ Eflfl 








Screen memory page 


□ Eflq 




t^q 




Maximum size of keyboard 
buffer 


□ Efla 








Repeat all keys 


□ EflB 




t51 




Repeat speed counter 


□ EfiC 




b5E 




Repeat delay counter 


□ EflD 




t53 




Keyboard shift/control flag 


□ EflE 








Last shift pattern 


□ EflF- 


-□Eq^ 


t55- 




Keyboard table setup pointer 


□Eqi 




fc57 




Keymode (Kattacanna) 


□ EqE 




tsa 




□ = scroll enable 


□Eq3 




fcsq 




RS-232 chip control 


□Eq^ 








RS-232 chip command 



186 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 




Decimal 


Description 


0515- 


■□Eqt 


ttl- 


-btE 


Bit timing 










RS-232 status 






hhA 




Number of bits to send 


□2qq- 


-□E^fi 


tt5 




RS-232 speed/code 


□ BRB 




tt7 




RS-232 receive pointer 


DE^C 








RS-232 input pointer 


□ ERD 




ttq 




RS-232 transmit pointer 


□ ERE 




t7D 




RS-232 output pointer 


□ ERF- 


-□Eao 


fc71- 


-fc7E 


IRQ save during tape i/0 


□ 3D0- 


-03D1 


7bfl- 


-7tq 


Error message link 


D3DS- 


-□3D3 


77^- 


-771 


BASIC warm start iinic 




-03D5 


77E- 


-773 


Cruncli BASIC tokens link 


□ 3Dt- 


-□3D7 


774- 


-775 


Print tokens link 


□ 3Dfl- 


-□3Dq 


77t- 


-777 


Start new BASIC code link 


□ 3Da- 


-□3DB 


77fl- 


-77q 


Get arithmetic element link 


□ 3DC 




7fi^ 




SYS A-reg save 


□ 3DD 




7fll 




SYS X-reg save 


□ 3DE 




7flE 




SYS Y-reg save 


□ 3DF 




7fl3 




SYS status reg save 


□ 314- 


-□315 


7flfl- 


-7aq 


IRQ vector (EftBF) 


□ 31t- 


-0317 


7R^- 


-791 


Break interrupt vector (FEDE) 


□ 31fl- 


-□3iq 


7qE- 


-793 


NMI interrupt vector (FEftD) 


□3ia- 


-□31B 


7R4- 


-795 


OPEN vector (F4Da) 


□ 31C- 


-□31D 


7qt- 


-797 


CLOSE vector (F34a) 


□ 31E- 


-□31F 


7qfl- 


-799 


Set-input vector (FEC7) 


□ 3ED- 


-□3E1 


&□□- 


-fl^l 


Set-output vector (F309) 


□ 3EE- 


-□3E3 


e,OE- 


-flD3 


Restore I/O vector (F3F3) 


U32A- 


-□3E5 




-fl^5 


INPUT vector (FEDE) 


□ 3Eb- 


-□3E7 


&Uh- 


-flD7 


Output vector (FE7a) 


□ 3Efl- 


-□3Eq 




-fl^9 


Test-STOP vector (F77 0) 


□ 3EA- 


-□3EB 


fll^- 


-fill 


GET vector (F1F5) 


□ 3EC- 


-□3ED 


fllE- 


-fll3 


Abort I/O vector (F3EF) 


03EE- 


-□3EF 


ai4 


-fll5 


USR vector (FEDE) 


□ 33D- 


-□331 


filb 


-fll7 


LOaD link 


□ 33E- 


-□333 


fllfl 


-fll9 


SaVE link 


□ 33C 


-□3FB 


flEfl 


-1019 


Cassette buffer 




-□FFF 


1DS4 


-4095 


3K RaM expansion area 




-IFFF 




-fll91 


Normal BASIC memory 


EDDD 


-7FFF 


fiiqE 


-3E7b7 


Memory expansion area 


flQDD 


-flFFF 


3E7tfl 


-3tat3 


Character bit maps (ROM) 



APPENDIX C — VIC 20 



187 



Hex Decimal Description 

qODO-qoOF Btab-^-ataTR video interface chip (6560) 

RllD-RlEF 3713t.-37151 VIA (6522) interface-NMI 

qiED-qiEF 3715E-371t7 VI R (6522) interface- IRQ 

R^DO-qSFF 37flflfl-3fl3q'=1 Alternate color nybble area 

qtD0-'=l7FF 3fl4QD-3fl'=111 Main color nybble area 

ADDO-BFFF An^hQ-AmSl Plug-in ROM area 

CDDD-FFFF 4qi5E-b5535 ROM: BASIC and operating 

system 



788 MACHINE LANGUAGE FOR COMMODORE MACHINES 



VIC 6560 Chip 



$9000 


Inter- 
lace 


Left IVIargin ( = 


= 5) 




36864 


$9001 


Top Margin ( = 25) 


36865 


$9002 


Scrn Ad 
bit 9 


# Columns ( = 


22) 




36866 




bItO 


# Rows ( = 23) 


Double 
Char 




$9004 




Input Raster Value: bits 8-1 




36868 


$9005 


Screen Address 
bits 13-10 


Character Address 
bits 13-10 


36869 


$9006 
$9007 


Light Pen Input 


Horizontal 
Vertical 


36870 
36871 


vpsUUo 
$9009 


Paddle Inputs 




X 
Y 




36873 


$900A 


_ ON 




Voice 1 






36874 


$900B 
$900C 


_ ON 
ON 




Voice 2 _ 

Frequency — 

Voice 3 


36875 
36876 


$900D 


ON 




Noise 






36877 


$900E 


Multl-Colour Mode ( = 0) 


Sound Amplitude 


36878 


$900F 


Screen Background Color 


Foregnd 
/Backg 


Frame Color 


36879 



Figure C.5 



APPENDIX C — VIC 6522 



189 



VIC 6522 Usage 



$9110 

$9111 

$9112 

$9113 

$9114 

$9115 

$9116 

$9117 

$9118 

$9119 

$911 A 

$91 1B 

$91 1C 

$91 ID 

$91 IE 
$91 IF 



DSR 


CTS 1 


1 DCD* 


Rl* 


DTP 


RTS 


Data 


In 


In 1 


1 In 


In 


out 


out 


In 



_T1-L 
T1-H 



_T1 Latch L 
T1 Latch H 



J2-L 
T2-H 



RS-232 Interface 
or, Parallel User Port 



Unused — see $91 IF 



DDRB (for $9110) 



DDRA (for $91 IF) 



RS-232 Send Speed; 
Tape Write Timing 



RS-232 Input timing 



Shift Register (*unused) 



T1 Control 


T2Cnt 


Shift Reg Control 


PB LE 


PA LE 


CB2: RS-232 Send 


CB1 C 


CA2: Tape motor Ctrl 


CA1 ai 


NMI: 


T1 


T2 


CB1: 
RS-232 
In 


1 


CA1: 
Restore 
button 




ATN 
out 


Tape 
sense 


Joysticks 

Button 1 Left | Down | Up 


Serial 
Data In 


Serial 
Clk In 



37136 

37137 
37138 
37139 
37140 
37141 
37142 
37143 
37144 
37145 
37146 
37147 
37148 
37149 

37150 
37151 



Figure C.6 



790 MACHINE LANGUAGE FOR COMMODORE MACHINES 



VIC 6522 Usage 



$9120 

$9121 
$9122 
$9123 
$9124 
$9125 
$9126 
$9127 
$9128 
$9129 
$91 2A 
$91 2B 

$91 2C 

$91 2D 
$91 2E 

$91 2F 



Joystk 
Right 


1 






Tape 
Out 












Keyboard Row Select 






Keyboard Column Input 


DDRB (for $9120) 


DDRA (for $9121) 


T1-L 
T1-H 

T1-L Latch 
T1-H Latch 


Cassette Tape Read; 
Keyboard & Clock 
Interrupt Timing 






T2-L 




Serial Bus Timing 






T2-H 




Tape R/W Timing 






Shift Register (*Unused) 


T1 Control 


T2 Ctrl 


Shift Register Contrl 


PB LE 


PALE 


Serial Bus Data Out 


CB1 
ContI 


Serial Clock Line out 


CA1 
ContI 


IRQ: 


T1 


T2 


CB1:* 
SRQ in 






CA1: 
Tape in 




*Unused: see $9121 



Figure C.7 



APPENDIX C — COMMODORE 64 



191 



Commodore 64: 

The Great Zero-Page Hunt: 

Locations $FC to $FF are available. Locations $EE to $2fl, $<E to 
$53, and $57 to $tn are work areas available for temporary use. 

Most zero-page locations may be copied to another part of memory so 
that their original contents can be restored after use. The programmer 
should take great care, however, in modifying the following locations, which 
are critical within the operating system or BASIC: $13, $lt to $lfl, 
$2Bto $3fl, $3a, $53 to $SA, $tfl, $73 to $flft, $^Dto $qft, $ftO 
to $aE, $Bfl to $BA; $C5 to $F4. 

Memory Map 



Hex 




Decimal 


Descriotion 


□ □□□ 




□ 


Chip directional register 


n n n 1 

□ □□I 




1 


onip i/u, memory ana lape 
control 


□ □03- 


■UUUA 


3-A 


Float-fixed vector 


□ □□5- 


■□□□b 


5-fc 


Fixed-float vector 


□ □□7 




7 


Search character 


□ □□fi 




fl 


Scan-quotes flag 


□□□q 




q 


TAB column save 


□□□a 




!□ 


□ = LOaD, 1 = VERIFY 


□ □□B 




11 


Input buffer pointer/number of 
subscripts 


□□□c 




IE 


Default DIM flag 


□ □□D 




13 


Type: $ FF= string; 
□ □= numeric 


□ ODE 




lA 


Type: $ fi □ = integer; 
□ □ = floating point 


□ □□F 




15 


DaTa scan/LIST quote/memory 
flag 


□ QIQ 




It 


Subscript/FNx flag 


□ □11 




17 


□ = INPUT;$4D = GET; 
$Hfi=REaD 


DUIE 




Ifi 


aTN sign/Comparison 
evaluation flag 


□ □13 




IR 


Current I/O prompt flag 




-□□15 


E^-El 


Integer value 



192 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 




Decimal 


Description 


U LJ ^ □ 




c c 




nuiMici. 1 ifjui di y oiling oiciui\ 


nni.7 - 


n m, A 

U U Ji u 






udoi iC/i 1 ipui di y oiling vouiui 


LJ LJ JJ 1 


0051 

LJ LJ ^ JJ 


E5- 




Stank for tpmnorarv Qtrinn^ 

WiClwiX \\J\ Iwl 1 lli^wl Cll y oil II lUw 


OOEE- 


□ □E5 


—J ^ 


37 


Utilitv Dointer area 


□ □Et- 


□ 02ft 


^ A- 


Z P 


Product area for multiolioation 


U U u XJ 


nnpr 

U U Q 


Z 1- 




Pnintpr" Qtart-nf-RA^IH 


n n PD- 

U U C JJ 


n n pp 

U U C ij 


Z c:_ 
*i J — 


Z L 
M b 


Pnintpr" Qtart-nf-wsiriahlpc 

1 \J\ \ 1 ICI . OlCll I \j\ Vdl ldl.^lC70 


U U C X 


nrr^n 

U U Jj u 


Z7- 


Z A 


rUHiici. old! I wi di 1 dyo 


U UJ JJ 


U U J u 


Z q_ 


c;n 


1 uiMioi . c?MU ui diidyo 






j jj 




nUllllCl. oUltl^ OlUld^C ^IIIUVIIIU 












U U -J ^ 


U U J o 




QZ 


1 Itilitx/ ctrinn nriintor 
^jiiiiiy oiiiiiy puiiiici 


u u J r 


nn^ft 

U LU Ll 




3 b 


Pnintpr' linriit-nf-iripmnrw 
1 wiiiid* iiiiiii \j\ iiidiiwiy 


U U J n 


LlLl 3 n 


D f — 


.c; A 


f^iirrpnt RAQIf^ linp niiinKpr 

wUIICiil D/AOIW IIIIC IIUIIIUCI 


U U □ D 


U U J 




b U 


Prp\/ini iQ PA^ir^ linp niimKor 

riCVIUUo DMO 1 V»/ llllo IIUIIIUCI 


\J \J D U 


Liu 3 Lt 


b Jj — 


r p 
'be 


Pnintpr* RA^IH Qtatpmpnt fnr 












u u J r 


nnz; n 

U U H U 


b J — 


LZ 
•b^ 


f^iirrpnt FlflTB lino niimKpr 


nnz:i.- 

U U H Jj 


nnz P 

U U H C 


b b- 


r r 
-b b 


Oi irrpnt "R H T B sHHrocc 
OUiicill 1/nJ.n dUUlcoa 




n nz z 

U U M 'I 


b r — 


L A 
- b u 


inpul VcUlUI 


nnz c; 


n nz L 


b n 


.7 n 


ourreru Vdriauic ridrnc 




n nz fl 

u u s u 


I Jj — 


7 p 


r^i irrpnt \/9ri£iHlp sHHrpcc 
wUiiciii vdiiduic? duuicoo 


n nz Q 


nnz n 

u U ^ n 


7 
r J 


.7 Z 


V/ariohIa nr\intar fnr TrnP/MPYT* 

variauic; puiniei lor run/nriAX 


LJ LJ ^ U 


LJ LJ " \^ 


7 c;. 


-7 L 
lb 


Y-^avp* OD-Qavp' BASIH 










nnintpr q£i\/p 


LJ LJ " J-' 




77 
r r 




nomnari^on wmhni 

1 i|jcii loii^i 1 wy 1 1 iii^ui 










flnr^i imi ilfitnr 
dwuui 1 luidiui 


DDAE- 


-□□53 


7 A- 

1 LJ 


-Al 

LJ -J 


Mi^npllanpniJ^ work arpa 

IVIIOV/wllCtI IwwUw Wwl i\ Cll wOj 










nnintprQ nnH Qn nn 

I^Vi/lllldO) dl ILI wl 1 


DDSA- 


-□□5b 


LJ 


LJ D 


Jumn vector for functions 

WUI 1 lli^ V wwiVI Iwl lUllwllVI lO 


□ □57- 


-□□b^ 


A7- 

LJ f 


n □ 


Mi^ppllanpoiiQ niimprip work 

IVIIO^^IICII twwUO 1 lUI 1 Id Iw VVUI l\ 










Cll wCl 


□ □tl 




~ f 




Acrijm#1" pynnnpnt 


nnp,?- 

U LJ O l_ 


LJ LJ O — J 




-101 


Anpiimafiti* nriAnticQS) 






l^E 




Accum#1 : sign 


□ □b? 








Series evaluation constant 










pointer 


□ □tfi 




1^4 




Accum#1 lii-order (overflow) 


□ □tR- 


-□□bE 


1^5- 


-IID 


Accum#2: exponent, and so on 


□ □bF 




111 




Sign comparison, Acc#1 versus 










#2 


□ □?□ 




HE 




Accum#1 lo-order (rounding) 



APPENDIX C — COMMODORE 64 



793 



Hex 




Decimal 


Description 


□ □71- 


•□□7E 


113- 


•114 


Cassette buffer length/series 










pointer 


□ □73- 


'□□fia 


115- 


13fl 


CHRGET subroutine; get 










BASIC character 


□□7a- 


■□□7B 


lEE- 


•1E3 


BASIC pointer (within 










subroutine) 


□ □flB- 


•□□flF 


13q- 


IA3 


END seed value 










Status word ST 


□□qi 




IAS 




Keyswitch PI a: STOP and 










RVS flags 


□□qe 




lAh 




Timing constant for tape 


□□q3 




1A7 




Load = ^; verify = l 










Serial output: deferred character 










flag 


□ □qs 




i<q 




Serial deferred character 


□□qt 




15^ 




Tape EOT received 


□□q7 




151 




Register save 


□□qfl 




15E 




How many open files 


□□qq 




153 




Input device, normally □ 


□□qft 




15^^ 




Output CMD device, normally 3 


□□qB 




155 




Tape character parity 


□□qc 




15t 




Byte-received flag 


□ □qD 




157 




Direct = $ fi □/R U N = □ output 










control 


□□qE 




15fl 




Tape pass 1 error log/character 










buffer 


□□qp 




15q 




Tape pass E error log corrected 


□□&□- 


■□□aE 


It^- 


■IbE 


Jiffy Clock HML 


□ □A3 




lt.3 




Serial bit count/EOI flag 






It^ 




Cycle count 


□□as 




lt>5 




Countdown, tape write/bit count 


□□at 




Itt 




Tape buffer pointer 


□□a? 




lt7 




Tape write leader count/read 










pass/inbit 


□□aa 




Itfi 




Tape write new byte/read 










error/inbit count 


□□aq 




itq 




Write start bit/read bit error/stbit 


□□aa 




17^ 




Tape Scan ;Cnt; Load; 










End/byte assembly 


□□as 




171 




Write lead length/read 










checksum/parity 


□ □ac- 


-□□aD 


17E- 


-173 


Pointer: tape buffer, scrolling 



794 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 




Decimal 


Description 


□ □AE- 


□ □AF 


17<- 


175 


Tape end address/end of 

program 


□ □BD- 


□ □31 


17t- 


177 


Tape tinning constants 


00B2- 


□ □33 


17 fl- 


17H 


Pointer: start of tape buffer 


QUBA 




Ifi^ 




1 = tape timer enabled; bit 
count 


□ □35 




Ifil 




Tape E0T/RSE3E next bit to 
send 


□ □Bt 




IflE 




Read character error/outbyte 
buffer 


□ □37 




ia3 




Number of characters in file 
name 


□ □Bfl 




Ifl^ 




Current logical file 


□ □Bq 




IflS 




Current secondary address 


□ □BA 




lat 




Current device 


□ □33- 


-□□BC 


lfl7- 


-Ififi 


Pointer to file name 


□ □BD 




laq 




Write shift word/read input char 


□ □BE 




mD 




Number of blocks remaining to 
write/read 


□ DBF 




iRi 




Serial word buffer 


□ □€□ 




l'=IE 




Tape motor interlock 


□ OCl- 


-□□CE 


1R3- 


-1R4 


I/O start address 


□ □C3- 


■OQCA 


1R5- 


-lit 


Kernel setup pointer 


□ □C5 




l'=17 




Last key pressed 


□ □Ct 




IRfl 




Number of characters in 
keyboard buffer 


□ □C7 




iqq 




Screen reverse flag 


□ □Cfl 




EDO 




End-of-line for input pointer 


□ □C^l- 


-□□CA 


E^l- 


-E^E 


Input cursor log (row, column) 


□ □CB 




£□3 




Which key: if no key 


□ □CC 




En< 




□ =flash cursor 


□ □CD 




—11—11— 

£□5 




Cursor timing countdown 


□ □CE 




3 n r 




Character under cursor 


n n o*p 




E^7 




Cursor in blink phase 


□ □D^ 




EDfl 




Input from screen/from 
keyboard 


□ □Dl- 


-□□Da 


E^R- 


-El^ 


Pointer to screen line 


□ □D3 




Ell 




Position of cursor on above line 


QUDA 




ElE 




□ = direct cursor; else 
programmed 


□ □D5 




E13 




Current screen line length 



APPENDIX C — COMMODORE 64 



795 



Hay 




Decimal 


L/croOr IfJUUi 1 


DDDh 




El/? 




Row where cursor lives 


□ 0D7 




E15 




Last inkey/checksum/buffer 


□ □Dfl 




Elfc 




Number of INSERTS 
outstanding 


□ DDR- 


□ 0F5 


E17- 


BAE 


Screen line link table 


□ □F3- 


□ OF^ 




EAA 


Screen color pointer 


□ □F5- 


□ DFt 


EAS- 




Keyboard pointer 


□ □F7- 


□ □Ffl 


2A7- 


E^6 


RS-232 Rev pntr 


OQFq- 


DDFfi 


E^R- 


E5^ 


RS-232 Tx pntr 


□ □FF- 


DIOA 


E5b- 


Ebt 


Floating to ASCII work area 


□ IDO- 


103E 


E5fc- 


31fl 


Tape error log 


□ IDD- 


□ IFF 


ESfc- 


511 


Processor stack area 


□ 500- 


OEsa 


51E- 


tDD 


BASIC input buffer 


□ E5S- 


□ EtE 


yoi- 


bl^ 


Logical file table 


0Et3- 


□ Etc 


bll- 


tE^ 


Device number table 


OEfcD- 


□ E7t 


tEl- 


t3^ 


Secondary address table 


□ 277- 


□ EfiD 


b31- 


t<Q 


Keyboard buffer 


□ Efil- 


□ EfiE 




■b<E 


Start of BASIC memory 


Q2&3- 


□ Efl^ 


t43- 




Top of BASIC memory 


□ Efl5 








Serial bus timeout flag 


OEflt 




yAh 




Current color code 


□ Efl7 




yA7 




Color under cursor 


□ Eflfl 




l,A& 




Screen memory page 


□ Eflq 




hA^ 




Maximum size of keyboard 
buffer 


□ EflA 




t50 




Repeat all keys 


□ EfiB 




t51 




Repeat speed counter 


□ EflC 




b5E 




Repeat delay counter 


□ EflD 




hS3 




Keyboard Shift/Control flag 


□ EflE 




hSA 




Last sliift pattern 


□ EflF- 


-□ERD 


t55- 


-t5t 


Keyboard table setup pointer 


□ Eqi 




t57 




Keyboard shift mode 


□ E^E 




t5Q 




□ = scroll enable 


□ ER3 




fcSR 




RS-232 control reg 


DER^ 




tbO 




RS-232 command reg 


DEq5- 


■□ERt 


bbl- 


-btE 


Bit timing 


□ Eq7 




bb3 




RS-232 status 


□ ERA 




tt< 




Number of bits to send 


□ ERR- 


-□ERA 


tt5 




RS-232 speed/code 


□ ERB 




tfc7 




RS232 receive pointer 


OERC 








RS232 input pointer 



796 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 




Decimal 


Description 


□ ERD 




yy^ 




RS232 transmit pointer 


05RE 




t70 




RS232 output pointer 




-OEftD 


t.71- 


-t7E 


IRQ save during tape I/O 


□ ERl 




fc73 




CI ft E (NMI) interrupt control 


OEfiE 




h7A 




CIA 1 timer A control log 






t75 




CIA 1 interrupt Log 


□ EA^ 




b7t 




CIA 1 timer A enabled flag 


□ EA5 




tj77 




Screen row marker 


02C0- 


-□EFE 


7DA- 


-7tb 


(Sprite 7) 


□ 300- 


-0301 


7bfl- 


-7tjR 


Error message link 


□ 3DE- 


-0303 


770- 


-771 


dAoIO warm start link 


Q3UA- 


-D305 


77E- 


-773 


Crunch BASIC tokens link 


□ 3Dfc- 


-0307 


17 A- 


-775 


Print tokens link 


□ 3Dfl- 


-030'^ 


77b- 


-777 


Start new BASlo code link 


03DA- 


-D30B 


77fl- 


-77'=l 


Get arithmetic element link 


□ 3DC 




730 




SYS A-reg save 


□ 3DD 




7fll 




SYS X-reg save 


03DE 




7flE 




SYS Y-reg save 


□ 30F 




7a3 




SYS status reg save 


□ 31D- 


-031E 


7&A- 


-7fl5 


OSR function jump (Dtr^iO) 


0314- 


-0315 


7flfl- 


-7fl'=l 


IRQ vector (EA31) 


□ 31t- 


-0317 


7R0- 


-7R1 


Break interrupt vector (FEfcb) 


□ 31fl- 


-031R 


7SE- 


-7m 


NMI interrupt vector (FE^7) 


03ia- 


-031B 


7R4- 


-7R5 


OPEN vector (F3'iA) 


031C- 


-031D 


7Rt- 


-7R7 


CLOSE vector (rcHl) 


□ 31E- 


-031F 


7Rfl- 


-7RR 


Set-input vector (FEOE) 


□ 3ED- 


-03E1 


fiOO- 


-flOl 


Set-output vector (FS5G) 


032E- 


-03E3 


flOE- 


-fl03 


Restore I/O vector (F3 3d) 


Q3EA- 


-03E5 


&UA- 


-flD5 


l__..X ..A aX A / TTI "1 ^ T \ 

Input vector (F157) 


□ 3Et- 


-03E7 


fiOb- 


-fl07 


Output vector (F 1 C A) 


□ 3Efl- 


-032"^ 


flOfl- 


-flOi^l 


Test-STOP vector (FbED) 


□ 3Ea- 


-D3EB 


fllO- 


-All 


GET vector (Fidt) 


□ 3EC- 


-03ED 


fllE- 


-□13 


Abort I/O vector (r d dr ) 


□ 3EE- 


-03EF 


HI/" 


-O 1 b 


U o K vector (r b b b) 


n ~i T n 


-□331 


filb- 


-fll7 


LUAi) linK (rHiib; 


□ 33E- 


-0333 


fllfi- 


-fliq 


SAVE link {F5ED) 


□ 33C- 


-D3FB 


fiEfi 


-IDiq 


Cassette buffer 


03-^0- 


-D37E 


a3s 




(Sprite 13) 


□ 3aD- 


-03BE 




-q5a 


(Sprite \A) 


□3cn- 


-D3FE 


SfcO 


-lOEE 


(Sprite 15) 


QADQ 


-07FF 


10E4 


-E047 


Screen memory 


n&DQ 


-RFFF 


EO^fl 


-4oq5R 


BASIC RAM memory 



APPENDIX C — COMMODORE 64 



797 



Hex 




Decimal 


Description 


o n n n 


n ti TP TP 


3E7tfl- 




Alternative: RON plug-in area 


T\ n n n 


-BFFF 






BON: BASIC 


n n n n 


-BFFF 




-5R151 


Alternate: RAN 


/-t n n n 


-CFFF 




-53E<7 


RAN memory, including 










alternative 


T% n H r1 


-DDdE 


^ T T X n 


-53dH4 


Video chip (bSbb) 


U U- 






-5<3DD 


bound cnip (bbol SID) 


DADO 


-DBFF 




-5t3iq 


Color nybble memory 


DCDD- 


-DCDF 




-5t335 


Interface chip 1, IRQ ( bSEt 










CIR) 


DDDD 


-DDDF 




-5b5Rl 


Interface Chip E, NNI (tEEb 










CIA) 


DDDD- 


-DFFF 




-535q4 


Alternative: character set 




-FFFF 




-b5535 


RON: operating system 




-FFFF 


S73AA- 


-t5535 


Alternative: RAN 



798 MACHINE LANGUAGE FOR COMMODORE MACHINES 



CIA 1 (IRQ) (6526) Commodore 64 





Paddle SEL 










Joystick 






$DCOO 


A . B 








R 


. L , D . U 


PRA 


56320 


Keyboard Row Select (inverted) 


$DC01 










Joystick 1 


PRB 


56321 


Keyboard Column Read 


$DC02 




$FF — 


All Output 




UUHA 




$DC03 






$00 — 


All Input 




DDRB 


56323 


$DC04 
$DC05 






Timer A 






TAL 
TAH 


56324 
56325 


$DC06 
$DC07 






Timer B 






TBL 
TBH 


56326 
56327 




















$DCOD 




Tape 
Input 




Timer Interr. 
B , A 


lER 


56333 














Time Timer 






$DCOE 








One Out 
shot pode 


PDL A 

out 1 start 


CRA 


56334 














Time Timer 






$DCOF 








One Out 
shot fnode 


PBC B 
out , start 


CRB 


56335 



Figure C.8 



APPENDIX C — COMMODORE 64 



799 



CIA 2 (NMI) 



(6526) 



Commodore 64 



Serial 
In 


Clock 

In 


Serial 
Out 


1 1 

Clock 
Out 


1 1 

ATN 
Out 


1 — : 1 

RS-232 
Out 


1 1 

Video 


Block 


DSR 
In 


CTS 
In 


F 


DCD* 
In 

>arallel I 


Rl* 
In 

Jser Po 


DTR 
Out 

rt 


RTS 
Out 


RS-232 

In 


In 


In 


Out 


Out Out 
$3F 


Out 


Out 


Out 


$06 For RS-232 








Timer A 














Timer B 









RS-232 
In 



Timer 
B 



Timer 
A 



Timer 
A Start 



Timer 
B Start 



PRA 
PRB 

DDRA 

DDRB 

TAL 

TAH 

TBL 

TBH 

ICR 

CRA 

CRB 



Figure C.9 



200 MACHINE LANGUAGE FOR COMMODORE MACHINES 



C64 Memory Map 
6566 Video — Sprite Registers 



Sprite Sprite 






7 


DOOO 


DOOE 


D001 


DOOF 


□027 


D02E 



Position 



Color 



D011 
D012 
D013 
D014 

D016 



Sprite Bit Positions 
5 4 3 2 



D010 
D015 
D017 
D01B 
D01C 
D01D 
D01E 
D01F 



X-position high 



Sprite Enable 



Y-expand 



Background Priority 



Multicolor 



X-expand 



Interrupt: Sprite collisn 



Interrupt: Sprite/Backgrd coll 



Sprite 


Sprite 





7 


53248 


53262 


53249 


53263 


53287 


53294 


53264 




53269 




53271 




53275 




53276 




53277 




53278 




53279 





C64 Memory Map 





6566 Video - 


Control and Misc. Registers 






Extnd Color 


Bit Map 


Dsply EnabI 


Row Selct . 


Y-Soroll 








Raster Register 










Light Pen Input 


X 
Y 



S326S 
53266 
53267 
53268 



X 


Reset 


Multl Color 


Colm Sel . 


X-Scroll 






A 





D018 




vm13 


Screen (Video Matrix) 
vm12 vmll 


vmlO 


Character Base 
cb13 cb12 cb11 


X 


53272 


D019 




IRQ 


IRQ sence 




1 1 


SSC , SBC 


RST 


53273 


D01A 






IRQ Enable 




Light 

Pen , 


Collision 
Spit Back 


Rastr 


53274 










COLOUR REGISTERS 








D020 












Exterior 


53280 


D021 












Background #0 


53281 


0022 












Background #1 


53282 


D023 












Background #2 


53283 


D024 












Background #3 


53284 


D025 












Sprite Multlcotor #0 


53285 


D026 












Sprite Multicolor #1 


53286 



Figure CIO 



APPENDIX C — COMMODORE PLUS/4 201 



SID (6581) Commodore 64 



V1 
D400 

D401 


V2 
D407 

D408 


V3 








V1 V2 V3 


D40E 
D40F 


— Frequency 


L 
H 


54272 54279 54286 

54273 54280 54287 


D402 


D409 


D410 


Pulse Width 


L 


CAn^A CAf^OH CilOOO 

54274 54281 54288 


D403 


D40A 


D411 







H 


54275 54282 54289 


D404 


D40B 


D412 


Voice Type 

NSE 1 PUL 1 SAW 1 TRI 




KEY 
1 1 1 


54276 54283 54290 


D405 


D40C 


D413 


Attacl< 
Time 

2ms-8sec 

1 1 1 


Decay 
Time 

6ms-24sec 

1 1 1 


54277 54284 54291 


D406 


D40D 


D414 


Sustain 

level 
1 1 1 


Release time 

6ms-24sec 

1 1 1 


54278 54285 54292 








Voices 
(write only) 








D415 








L 


54293 






D416 


Filter Frequency 


H 


54294 






D417 


Resonance 

1 1 1 


Filter voices 

|eXT| V3 I V2 I VI 


54295 






D418 


Passband 

V3 

OFF 1 HI 1 BD 1 LO 


1 


Master 

Volume 

1 1 1 


54296 



Filter & Volume 
(write only) 



Paddle X 54297 

Paddle Y 54298 

Noise 3 (random) 54299 

Envelope 3 54300 

Sense 
(read only) 

Special voice features (TEST, RING MOD, SYNC) are 
omitted from the above diagram. 

Figure C.11 



D419 
D41A 
D41B 
D41C 



202 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Commodore PLUS/4 "TED" Chip- 
Preliminary 

At time of publication the Commodore 264 (alternatively called Plus/4) and 
a related machine, the Commodore 16, are not commercially available. 
Design details could change before commercial release. 

On the prototype units, much of zero-page is the same as for VIC and 
Commodore 64; in particular, the Basic pointers (SOB, SOV, etc.) are the 
same. 

Memory Map, Preliminary 

Much of zero-page is the same as for the Commodore 64. Some differ- 
ences, and other information: 



Hex 




Decimal 


Description 


□ □73- 


□□aa 


115-13a 


(CHaRGET not present) 


□□q? 




151 


How many open files 


□□qa 




152 


Input device, normally □ 


□ □RR 




153 


Output CMD device, normally 3 


□□ac 




17S 


Current logical file 


□ □fiD 




173 


Current secondary address 


□ QAE 




17^ 


Current device 


□□aF- 


□ □BD 


175-17fc 


Pointer to file name 


□□ca- 


□□cq 


EDO-B^l 


Pointer to screen line 


□□ca 




EUE 


Position of cursor on above line 


□ □CD 




RUS 


Row where cursor lives 


□ □EF 




23q 


Number of characters in 








keyboard buffer 


□ 3K- 


-□315 


7aa-7aq 


IRQ vector (CE^E) 




•□317 


7q^-7qi 


Break interrupt vector (?AAB) 


□3ia- 


■□3iq 


7qE-7q3 


OPEN vector (EF53) 



(Most other vectors are similar to the C64, but are two locations lower) 

□ 5^^-^5DE lea^-lEaE USR program jump 
D5nq-D51E lEaq-lEqa Logical file table 

□ 513-0510 lEqq-130a Device number table 

□ 51D-^5Efc 13^q-13ia Secondary address table 

□ 5E7-^53^ 13iq-13Ea Keyboard buffer 

□ a^^-DBE7 2DAei-3DA7 Color memory 

□ CDD-DFE7 3^7E-4^71 Screen memory 



APPENDIX C — B SERIES 



203 





IN: 




IN: IN: IN: 


OUT: 


OUT: 


OUT; 


OUT: 




SERIAL CLOCK ^ ^ TAPE 


TAPE 
, MOTOR 


ATN 


SERIAL 


TAPE 
CLOCK 




FFOO 
FFOl 












T1 


L _ 
H " 


FF02 
FF03 
rrut 
FF05 






TIMERS 




T2 

T3 


1 1 


FF06 


TEST 




ECM , BMM , BLANK 


ROWS . 


Y-ADJUST 


FF07 


RVS OFF , 


PAL , FREEZE , MCM 


COLUMNS 


X-ADJUST 


FF08 


KEYBOARD LATCH 


FF09 


IRQ FLAG 




1 i 




LP 


PAST 




rrUA 


lER 




T3 . V -v 'l^ft T2 , 


T1 


LP 


RAST 




FF08 






RASTER CONTROL 








FFOC 














FFOD 






CURSOR CONTROL 








FFOE 
FFOF 






SOUND: 


VOICE 1 
VOICE 2 








FF10 












VOICE 


2 HI 


rr 1 1 


SOUND SELECT 


VOLUME 


CC 1 o 

rr 1 z 


1 BIT MAP BASE 


R BANK 


VOICE 


1 HI 


PP 1 "5 
pp 1 J 


CHARACTER BASE 


SCLOCK 


STATUS 


FF14 


VIDEO MATRIX 




FF15 
FF16 






LUMINANCE 




COLOR 



1 


FF17 














2 


FF18 




1 


ACKGROUND COLORS 


3 


FF19 


■ . •' 












4 


FF1A 


- ' 














FF1B 






CHARACTER POSITION RELOAD 






FF1C 














1 


FF10 


VERTICAL LINE REGISTER 


FFIE 


HORIZONTAL POSITION REGISTER 


FF1F 




BUNK COUNT 


V SUBADDRESS 



65280 
65281 
65282 
65283 
65284 
65285 
65286 
65287 
65288 
65289 
65290 
65291 
65292 
65293 
65294 
65295 
65296 
65297 
65298 
65299 
65300 
65301 
65302 
65303 
65304 
65305 
65306 
65307 
65308 
65309 
65310 
65311 



FF3E 






ROM SELECT 




65342 






WRITE ONLY: 






FF3F 




RAM SELECT 




65343 



Figure C.12 



204 MACHINE LANGUAGE FOR COMMODORE MACHINES 



IDDD-FFFF 4QRt-t5535 BASIC RAM memory 
flDOD-FFFF 3E7ta-t5535 ROM: BASIC 
FF00-FF3F t5EflD-t5343 TED I/O control chip 

B Series (B-128, CBM-256, etc.) 
The Great Zero-Page Hunt 

Zero page has a different meaning on the B series. There are several 
zero pages. Usually, you'll want to use values from bank 15 (the ROM 
bank, where system variables are kept); but if you are writing programs 
that will reside in a different bank, you'll have all of zero page (except 
locations □ and 1) completely at your disposal. 

If you need space in bank 15 zero page, you'll need to do some looking 
around. Addresses $Et to $FF are not used by the system. Locations 
$ED to $EB and to $fcE are work areas available for temporary 
use. 

Most zero-page locations may be copied to another part of memory so 
that their original contents can be restored after use. The programmer 
should take great care, however, in modifying the following locations, which 
are critical within the operating system or BASIC: $1A, $1D to $51, 
$5D to $A1, $A3, $5B, $7fl, SflS-fl?, $RE to SAB, $C0 to $E5. 

Memory Map 

The following information applies to B systems released after April 1983, 
which contain a revised machine language monitor. (If POKE b , □ : SYS 
t doesn't bring in a monitor display complete with a "period" prompt, you 
have an incompatible version.) 

Notable features as compared to previous Commodore products include: 

— CHRGOT is no longer in RAM. Wedge-type coding must be inserted at links 
$DE'^Eand$QEao, which Is likely to make the job easier. 

—BASIC vectors have "spill." Now, for example, there are discrete "start of 
variables" and "end of variables," distinct from end-of-BASIC and start-of- 
arrays. Three-byte vectors (including bank number) are not uncommon. 

—The "jump table" at top of memory is still accessible and reasonably consistent 
with previous Commodore products. 

—Simple machine language programs will fit Into the spare 1 K of RAM at 
$04D0to$D7FF without trouble. Large programs must be Implemented 



APPENDIX C — B SERIES 205 



either by plug-in memory (RAM or ROM) in bank 15 or by being placed into 
another bank (preferably bank 3). Supplementary code will be needed to 
make all the coding components fit. 

The following map contains BASIC addresses specific to the B256/80; 
references to banks OXo A are also specific to that machine. Most of the 
map is of general usage, however. 



ALL BANKS: 

□ □□□ □ 

□ □□1 1 

BANK 0: Unused. 

BANK 1: 
□□□5-FDDD 
FABE-FBOQ 

BANK 2: 

B256: 
□DOE-FFFF 

B1E&: 
□005-FFFF 



tSD"^ execution register 
bBDR indirection register 



BASIC program (text) RAM 
Input buffer area 



E-fc5535 BASIC arrays in RAM 



E-fc5535 



BANK 3: (B256 only) 
□□□E-7FFF a-357fc7 
flDDO-FFFF 3E7tfl-t5535 

BANK A : (BESt only) 
□□□E-FBFF E-t4511 

FCDD-FCFF t451E-t47t7 
FDOD-FFFF t47tfl-b5535 

BANKS 5 to 14: Unused. 

BANK 15: 



BASIC variables, arrays and 
strings 

Key definitions 

Unused RAM. 

BASIC variables in RAM 

BASIC strings (top down) in 
RAM 

Unused RAM (descriptors?) 
Current KEY defiriitions 



□ □□E- 


■QQUA 


E- 


■A 


USR jump 


□ □□5- 


'□□□a 


5- 


■fl 


TI$ output elements: 










H,M,S,T 


□ □DR- 


■□□□B 




-11 


Print Using format pointer 


□ □□C 




lE 




Search character 


□ □□D 




13 




Scan-between-quotes Flag 


□ □□E 




lA 




Input point; number of 










subscripts 


□ □□F 




15 




Catalog line counter 


□ QID 




It 




Default DIM flag 


□ □11 




17 




Type: E55= string, □ = integer 



206 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



n n 1 3 

UU Jl c 




1, ft 

JJ U 




Type: 1 E fl = integer, 
= floatina DOint 


n n 1 








Crunch flaa 


nm z 
UU Ji'i 




\Z LI 




Subscript index 


UU Jl 3 




1 JJ 




lnput= 0; get= t4; reacl = 15S. 


n n 1. c 

U U Jj b — 


U U JJ n 






Disl< status worl< values 


n n 1 n 

U U Ji n 




L- □ 




Current I/O device for prompt 
suppress 


nm.R— 

U U ii D — 


U Ll Jl 


E7- 


•Sfl 


Integer value 


nni.n_ 

U U JJ 1/ 


LI U JJ J. 


gq- 


■31 


Descriptor stacl< pointers 


nnpri— 
u u c u~ 


U U C Jl 


32- 


33 


Vector to string descriptors 


U U C C"~ 


nnpR 

UUCD 




43 


Miscellaneous work pointers 


u u cu- 




M —1 


■Ah 


Start-of-BASIC pointer 


rl n 31? 
UUcf - 


n n ^3 n 
u U J u 


Z 7- 




End-of-BASIC Dointer 


n n 1 
UUdl- 


-U U J c 




D U 


Rtart-nf-Varlables Dointer 


UUdd- 


■ U U J H 






End-of-Variables Dointer 


U U J 3- 


-U U J D 




-q4 


Start-of-Arravs Dointer 


U U J r - 


'U U J □ 


^ -J 




End-of-Arrays pointer 


nmQ- 

U U J n 


U U 3 £1 


-J 1 


-Sfl 


Variable work pointer 




-nmr 

U U ^ 




-tiQ 


Bottom-of-Strings pointer 


n m 

uUdU- 


- U U J £i 


LL- 
CS jj 


DC 


IJtilitv strina oointer 


u u J r - 


- U U H Jl 


D J 




Top of string memory pointer 


nnziP- 

U U H C 


U U H J 




-ti7 


Current BASIC line number 


n nz z _ 

U U M H " 




f. A- 


O 1 


Old BASIC line number 




-0047 


70- 


-71 


Old BASIC text pointer 


n nz Q 
U Um n - 


n n z n 




-1 c 

1 M 


Data line number 


nnzR 
u u ^ D- 


n nz r 


r zi 


-7 


Data text oointer 


nnzn. 


-finz'P 

U LJ H Ij 


77- 


-7fl 


inout oointer 


u u ^ r - 


U U D U 


7q- 


-AG 

LJ LJ 


Variable name 


U U 13 JJ 


U U P J 


LJ M 


-83 


Variable address 


U U _J *-1 


LJ l_l ^ u 


&A- 


-flb 


For-loop pointer 


U U 3 1 


LJ Ul ^ LJ 


&1- 


-flfl 


Text pointer save 


nrma 

U U 3 n 








Comparison symbol 
accumulator 


□ □5B- 


-DD5D 


qi- 


-qe 


Function location 


□ □5E- 


-DDtO 






Working string vector 


□ □tl- 


-□□t3 


R7- 


-qq 


Function jump code 


□ □t4- 


-OOtE 


100 


-110 


Work pointers, values 


□ OfcF 




111 




Exponent sign 


QD70 




112 




Acum string prefix 


D071 




113 




Acum#1 : exponent 


□ □7E 


-□075 


114 


-117 


Accum#1: mantissa 



APPENDIX C — B SERIES 



207 



□ □7t 




iia 




□ □77 




iiq 




□ Q7a 




l^Q 




□ □7R- 


□ □7E 


lEl- 


•lEti 


□ □7F 




127 




□ □&□ 




lEa 




□ Dfll- 


UQ&A 


lEq- 


■135 


□ OfiB- 


□ □67 


133- 


-135 


DDflfl- 


□□aq 


13ti- 


■137 


□ □flB- 


□□aE 


i3q- 


■14E 


□ □SF 




1^3 




□□qo- 


□□q2 




-14 1 


□□q3- 


□□qs 


147- 


-14H 


□ □Rfc- 




15D- 


-155 


□□qaa 






□oqq- 


□□qs 


153- 


1 f— r— 

-155 


DORC 




15t 




□ □RD 




157 




□ □RE 




15a 




□ □^F 




i5q 




□ □AO 








ODRl 




iti 








ltd 




□ □Afc- 


■□□Aa 


Ifctj- 


-ita 


□ OftR 




ifcq 




□ □AA 




17 □ 




□ □ftB 




171 




□ □AC- 


-□□AD 


175- 


-17 3 


□ □AE- 


-□□B3 


174- 


-i7q 


□ □B^ 




lao 




□ □B5 




lai 




onB7- 


-□□Ba 


ia3- 


-ia4 


DDBR- 


-□□BA 


las- 


-lafc 


□ □BB- 


-□□BC 


ia7- 


-laa 


□ □BD 




laq 




ODBE 




iqa 




□ DBF 




iqi 




□ □CD- 


-□□CI 


iqa- 


-iq3 


□ □C5- 


-□□C3 


iq^- 


-iq5 



Accum#1 : sign 

Series evaluation constant 

pointer 

Acum#1 hi order (overflow) 
Accum#2 

Sign comparison, Acc#1 versus 
#2 

Acc#1 low-order (rounding) 
Series, work pointers 
BASIC text pointer 
Input pointer 
DOS parser work values 
Error type number 
Pointer to file name 
Pointer: tape buffer, scrolling 
Load end address/end of 
program 

I/O start address 

Status word ST 

File name length 

Current logical file 

Current device 

Current secondary address 

Input device, normally 

Output CMD device, normally 3 

INBUF 

Keyswitch PI A: stop key, etc. 
IEEE deferred flag 
IEEE deferred character 
Segment transfer routine vector 
Monitor register save 
Monitor stack pointer save 
Monitor bank number save 
Monitor IRQ save/pointer 
Monitor memory pointer 
Monitor secondary pointer 
Monitor counter 
Monitor miscellaneous byte 
Monitor device number 
Programmable key table 
address 

Programmable key address 



208 MACHINE LANGUAGE FOR COMMODORE MACHINES 





-UUL r 


1 Q t_ 


1 Q Q 

Ji n T 


Drtintarc tn ohsinnp 

roinieib lu i/iiaiiyts 
prOyrammaDie Key lauic 


n n o n 


n n o n 
-□□CH 


!!] n n 


3 n 1 
dUl 


rOinxer lo screen iirie 


OOCft 




EOE 




Screen line number 


□ OCB 




dud 




rosition OT cursor on line 


□ □CC 




3 n /■ 




u — lexi moue, eise grapriics 
mode 


□ UCD 




D n c 




iveypress variauie 


□ OCE 




n r 
cUh 




uiQ cursor coiumn 


n n TTi 

□ UCF 




^ n "5 
d U r 




UIQ cursor row 


□ UDU 




D n A 
c U □ 




iNew cnaraCicr iiay 


n n "n 1 




D n a 
c U n 




iNumuor uT K6yo in Kcyuuciru 
buffor 


PI n "pv "n 




3 1 n 
d Jj U 




uuoies Tiag 


n n 




d Jj Jj 




men Key counier 






did 




Cursor type flag 


n n T-\ i— 




did 




ocreen line lengin 


n n r\ r 
□ UDb 








iNUmuer ot Keys in Key uuner 


□ □D7 




E15 




Key repeat delay 


n n T\ n 

□ □Do 




dlb 




Key repeat speed 


n rrn Q 


n rrn 7\ 
-UUUii 


dli r- 


31 A 
-C Jl u 


1 emporary vanauics 






3 1 Q 
c Jj n 




/^i iri*Ant Ai itm it Ahoro/^tAr 

uurrsni ouipui cnaracicr 






P 3 n 
ecu 




Trtr* lino of /^i irront c/^roon 
■ up lliio Ul OUIlclll ouiccll 


n rTnr\ 




3 P 1 
CC ii 




Douum line OT sortjcn 






P 3 3 
CCd 




1 Aft A^AA At AI lt*l*Ant OAI*AAn 

Len OT C/Urrcni screen 


n nnp 




CC3 




rviyni euyc ui boreeii 


n m? n 
U U£i U 








t^A\/0 ' ^ CI C — MArtA" 1.3 7 — I^Al/ 

rseys. c ZD □ — none, jj c r — Key, 

111 — chift 

jj ij ij — snin 


DDEl 




EES 




Key pressed: 255 = no key 




-U Uri3 


3 3 C_ 

d d b- 


3 3a 
-c c n 


Line wrap tsiis 






d5b 




Hex to Dinary siaging area 


n 1 n n 


n 1 n 7\ 
-U JjUA 


3 C L 

dbb- 


3 L L 
-ebb 


Nil im APIA tA AC^II lAfArl^ Of* AO 

iNunienc 10 mol/Ii won\ area 


n 1 n n 
U Jj u u- 


n 1 W 


3 C L. 

cab- 


- 3 Jj U 


OlauiN dlect 


OlFF 




511 




Stack pointer save location 


DEOO- 


-OEDF 


51E- 


-5E7 


File name area 


OEIO- 


-DEEb 


5Ea- 


-55D 


Disk command work area 


□ 555- 


-□S5b 


5R7 




Miscellaneous work values for 
WRIT, etc 


0E57 




5qq 




"Bank" value 










Output logical file (CMD) 


□Esq 




bDl 




Sign of TAN 



APPENDIX C — B SERIES 



209 





-0E5D 


bOE- 


-^□5 


Pickup subroutine; 










miscellaneous work values 


□asE- 


-0E7b 


^□b- 


-1.3U 


PRINT USING working 










variables 


□ EflD- 


-DEfll 




-hAl 


Error routine link [6555] 


□ EflE- 


-□Sfl3 


fc-^E- 


-t^3 


Warm start link [flSCD] 


□ Efl^- 


-□EflS 




-hAS 


Crunch token link [flflCE] 


□ Efit- 


-DEfi? 




-hA7 


List link [aqp^] 


□aaa- 


-OEflR 


hA&- 




Command dispatch link [fl754] 


□ EflR- 


-□EflB 


hSQ- 


-t51 


Token evaluate link [qtBl] 


□ EflC- 


-□EflD 


fc5E- 


-t53 


Expression eval link [q5C4] 


□ EflE- 


-□EflF 




-b55 


CHRGOT link [BaEC] 


□ ERD- 


-OEHl 




-fc57 


CHRGET vector [Ba3E] 


□ ERE- 


-□Eq3 


b5fl- 


-bsq 


Float-fixed vector [BaiE] 


DER4- 


-0ER5 


tbD- 


-ttl 


Fixed-Float vector [qD3q] 


DEqt- 


-□ER7 


ttE- 


-tb3 


Error trap vector 


□ ERfl- 


-□Eqq 




-bb5 


Error line number 


□E^a- 


-□ERB 


bbb- 


-bb7 


Error exit pointer 


□ ERC 








Stack pointer save 


OERD- 


-□ERF 




-t71 


Temporary TRaP, DISPOSE 










bytes 


OEAD- 


-□EAB 


t7E- 


-t77 


Temporary INSTR$ bytes 


□ Eftt- 


-□EA? 


fc7fl- 


-t7q 


Bank offset 


□ 300- 


-□3D1 


7fcfl- 


-7fcq 


IRQ vector [FBEq] 


□ 30E- 


-□3^3 


77^- 


-771 


BRK vector [EEEl] 




-□3^5 


77E- 


-773 


NMI vector [FCaa] 


□ 3Db- 


-□3D7 


77^- 


-775 


OPEN vector [FbBF] 


□ 3Dfl- 


-□3^n 


77t- 


-777 


CLOSE vector [F5ED] 


□ 30a- 


-□3^B 


77fl- 


-77q 


Connect-input vector [F5^q] 


□ 3DC- 


-□3DD 


7fl^- 


-7fll 


Connect-output vector [F5a3] 


□ 3DE- 


-□3DF 


7flE- 


-733 


Restore default I/O vector 










[Fbat] 


□ 31D- 


-□311 


l&A- 


-7fl5 


Input vector [F^qC] 


□ 31E. 


-□313 


7fib. 


-757 


Output vector [F4EE] 


U31A- 


-□315 


7flfi 


-7flq 


Stop key test vector [FqfcB] 


□ 31b 


-□317 


7q^ 


-7qi 


GET vector [FA3B] 


□ 31fl 


-□3iq 


7qE 


-7q3 


Abort all files vector [Ft7F] 


031R 


-0316 


7q4 


-7q5 


Load vector [F7<t] 


□ 31C 


-□31D 


?qb 


-7q7 


Save vector [Ffl^C] 


□ 31E 


-□31F 


7qfl 


-7qq 


Monitor command vector 



[EE77] 



210 MACHINE LANGUAGE FOR COMMODORE MACHINES 



□3ED-03E1 flQO-flQl 
□354-D3E5 flO<-flD5 



□ 3Et- 


■□3E7 




•a^7 


□ 3Ea- 


■□3ER 


ana- 


•a^q 


□3aa- 


■□3EB 


ai^- 


ail 


□ 3EC- 


-□3ED 


aiE- 


•ai3 


□ 3EE- 


■□3EF 


ai4- 


•ai5 


□ 33D- 


-□331 


aib- 


•ai7 


□ 33E- 


•0333 


aia- 


•aiq 


□ 334- 


■□33D 


aED- 


•BEq 


□ 33E- 


■□347 


a3^- 


■a3q 


03A&- 


□ 351 


a4^- 


•a^q 


□ 35E- 


□ 354 


a5^- 


•a5E 


□ 355- 


■□357 


a53- 


•a55 


□ 35fl- 


■□35A 




•flsa 


□ 35B- 


■□35D 


asq- 


ati 


□ 35E 




atE 




□ 35F 




ati3 




□ 3t^ 




ab4 




□ 3tl 




ats 




□ 3b3- 


■□3tb 


at7- 


37^ 


□ 3bq 




a73 




□ 3tR- 


□ 3fcB 


a74- 


fl75 


□ 3bF- 


□ 371 


a7q- 


aai 


□ 375 




aa5 




□ 37t- 


□ 377 


aab- 


aa7 


□ 37A 




aq^ 




□ 37B 




aqi 




□ 37C 




aqE 




□ 37D 




aq3 




□ 3fl^- 


□ 3fiE 


aqt- 


aqa 


□ 333- 


□3qt. 


aqq- 


qia 



Keyboard control vector [E^IF] 
Print control vector [ED IF] 
IEEE send LSa vector 

[FE74] 
IEEE send TSa vector 

[FEaD] 
IEEE receive byte vector 

[F30R] 
IEEE send character vector 

[FEq7] 
IEEE send untalk vector 

[FEaB] 
IEEE send unlisten vector 

[FEaF] 
IEEE send listen vector 

[FE34] 

IEEE send talk vector [FE3^] 
File logical addresses table 
File device table 
File secondary address table 
Bottom of system memory 
Top of system memory 
Bottom of user memory 
Top of user memory 
IEEE timeout; □ = enabled 
O = load; IE a = verify 
Number of open files 
Message mode byte 
Miscellaneous register save 
bytes 

Timer toggle 

Cassette vector (dead end) 
Relocation start address 
Cassette motor flag (unused) 
RS-232 control, command 
RS-232 status 
RS-232 handshake input 
RS-232 input pointer 
RS-232 arrival pointer 
Top of memory pointer 
Programmed key lengths 



APPENDIX C — B SERIES 



211 



□ 3^7 








RVS flag 


Q3Rfl 




RED 




Current line number 


□3qq 








Temporary output character 










save 


03qft 




Rsa 




□ = normal, E 5 5 = auto insert 






RS3 




D = scrolling, 1 E fi = no scroll 


□ 3'=IC 








Miscellaneous work byte for 










screen 


□ 3^0 




R55 




Index to programmed key 


□3qE 








Scroll mode work flag 


Q3qF 




qa? 




Bell mode flag 


□ BAD 








Indirect bank save 


03A1- 


-D3aft 


RER- 


-R3fl 


Bit mapped tab stops 


□ 3aB- 


-U3BA 


R3R- 


-R^a 


Keyboard input buffer 


Q3B5- 


-D3Bt 


KR- 


-R5D 


Key word link [ERIB] 


□ 3Ffl- 


-D3FR 


IDlt- 


-1D17 


Restart vector 


□ 3Fa- 


-D3FB 


IDia- 


-IDIR 


Restart test mask 


□ -^DD- 


-D7FF 


1D2<- 


-ED47 


Free RAM (reserved for DOS ) 


□ 


-DFFF 


ED^fl- 


-4DS5 


Reserved for plug in RAM 




-IFFF 


^DRt- 


-fliqi 


Reserved for plug in DOS ROM 




-7FFF 


fllRE- 


-E37ti7 


Reserved for cartridges 


&UDQ- 


-BFFF 


3E7tfl 




BASIC ROM 


CDDD- 


-CFFF 


4R15E 


-53E47 


Unused 


DDDD 


-D7CF 


53E4fl 


-55E47 


Screen RAM 


DflOD 


-DflDl 


55ERt 


-55ER7 


Video controller hSAS 


DADO 


-DAIC 


SSflDfl 


-SSABEd 


Sound interface device tSfll 


DBDD 


-DBDF 




-StD?^ 


Complex interface adaptor 










bBEt 


DCDD 


-DCDF 


5t.3ED 


-5t335 


Complex interface adaptor 










t,5Et 


DDDD 


-DDD3 


5t57t 


-5t57q 


Asynchronous communications 










lA b551 


DEDD 


-DED7 


5t.a3E 


-5tfl3q 


Tri Port Interface Adaptor 










t5E5 


DFDD 


-DFD7 


57Dflfl 


-57Dq5 


Tri Port Interface Adaptor 










t5E5 


EDDD 


-FFFF 


573^^ 


-t5535 


Kernal ROM 



The above table shows contents for the link and vector addresses at $0280 
to $0295; these are taken from a recent B-128. 



1 



272 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



6545 CRT Controller 



D800 
55296 


D801 
55297 


Typical Value 
(Decimal) 





Horizontal Total 


108 or 126 or 127 


1 


Horizontal Cliar Displayed 


80 


2 


Horizontal Sync Position 


83 or 98 or 96 


3 


y Sync Width ^ 


15 or 10 


4 


Vertical Total 


25 or 31 or 38 


5 


Vert Total Adjust 


3 or 6 or 1 


6 


Vertical Displayed 


25 


7 


Vert Sync Position 


25 or 28 or 30 


8 


Mode 





9 


Scan Lines 


13 or 7 


10 


Cursor Start 


96 (blink) or 
or 6 (underline) 


11 


Cursor End 


13 or 7 


12 
13 


1^ 

— Display Address — 

L 






14 
15 


u 

— Cursor Address — 

L 


Varies 
Varies 


16 
17 


1^ 

— Liglit Pen In 

L 







Most Registers are Write Only 14/15 are Read/Write 

16/17 are Read Only 
Registers 10, 14 and 15 change as the cursor moves 

Figure C.13 



APPENDIX C — COMMODORE 128 



213 



6525 Tri Port 



DEOO 


NRFD 


NDAC 


EOl 


DAV 


ATN 


RFN 




56832 


DE01 


Sense 


Cassette 
Motor 


Out 


ARB 


Network 
Rx 


Tx 


SRQ 


IFC 


56833 


DE02 




IRQ 


ACIA 


IP 


CIA-2 


IEEE 


PWR 


56834 


DE03 


Data Direction Register For DEOO 


56835 


UtU4 


Data Direction Register For DE01 


OOOOO 




IRQ 




ACIA 


IP 


CIA-2 


IEEE 


PWR 


OOOOf 


DE06 


CB 




CA 

Graphics 




IRQ 
stack On 


56838 


DE07 


Active Interrupt Register 


56839 










6525 Tri Port 2 








DFOO 


Keyboard 


57088 


DF01 


Select 


57089 


DF02 


CRT 
Mode 


Keyboard Read 


57090 


DF03 


Data Direction Register for DFOO (out) 


57091 


DF04 


Data Direction Register for DF01 (out) 


57092 


DF05 


Data Direction Register for DF02 (in) 


57093 


DF06 


Unused 


57094 



Figure C.14 



214 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



COMMODORE 128: 

Memory Maps 

These maps apply to the machine when used in the 1 28K mode. When 
used in the 64 mode, the machine's map is identical to that of the Com- 
modore 64. Since the RAM work area is 7K in size — as compared to the 
Commodore 64 with 1 K — the map can be huge; it is somewhat abridged 
here. 

Architecture: "Bank numbers" as used in BASIC BANK and the MLM 
addressing scheme are misleading; in fact, they are more correctly "con- 
figuration numbers." Banl< shows RAIVI level 0, which contains work 
areas and the user's BASIC program. Bank 1 also shows RAM, this time 
(for addresses above hexadecimal □^□□) level 1 which contains vari- 
ables, arrays, and strings. Other "banks" are really configurations, with 
various types of ROM or I/O overlaying RAM. Thus, Bank 15 (the most 
popular) is ROM and I/O covering RAM bank 0. Bank 14, however, is 
ROM and the character generator overlaying RAM Bank 0. Architecture 
Is set so that addresses below $ □ □ reference Bank only. Other bank 
switching (more complex than the simplified 16-bank concept) is accom- 
plished via storing a mask to address $FFDD, or calling up prestored 
masks by writing to $FFD1-FFD4. 

The Great Zero-Page Hunt: 

Locations $FA to $FF are available. Locations $EA to $2C, $50 to 
$55, and $5'^ to $tS are work areas available for temporary use. 

Most zero-page locations may be copied to another part of memory so 
that their original contents can be restored after use. The programmer 
should take great care, however, in modifying the following locations, which 
are critical within the operating system or BASIC: $15, $lfl to $1A, 
$5D to $3E, $5t to $57, $10 to $^A, $A0 to $65, $A7 to $Afl, 
$BA to $BE., $BD, $CD, $Cfl to $Dfl. 



APPENDIX C — COMMODORE 128 



215 



Memory Map 

ALL BANKS: 



Hex 




Decimal 


Description 


□ □□0 




□ 


I/O directional register 


□ DDI 




1 


I/O port, similar to C64 


□ □□5- 


■QUDA 


2-4 


SYS address, MLM registers 








(SR, PC) 


□ □□5- 


■□□□q 


5-q 


SYS, MLM register save (A, X, 








Y, SR/SP) 


OODA 




1^ 


Scan-quotes flag 


□ □□B 




11 


TAB column save 


□ □□C 




12 


□ = LOAD, 1= VERIFY 


□ OOD 




13 


Input buffer pointer/number of 








subscripts 


□ □□E 




lA 


Default DIM flag 


□ □□F 




15 


Type: FF = string; □□ = numeric 


□ □ID 




It 


Type: fl □ = integer; 








□ □^floating point 


□ □11 




17 


DATA scan/LIST quote/memory 








flag 


□ □IB 




Ifl 


Subscript/FNx flag 


□ □13 




iq 


□ = INPUT;$4D = GET; 








$'=ifl = REaD 


QUIA 




2^ 


ATN sign/Comparison 








evaluation flag 


□ □15 




21 


Current I/O prompt flag 


□ □It- 


■□□17 


22-23 


Integer value 


□ □Ifl 




24 


Pointer: temporary string stack 


□ □IR- 


■□□53 


25-35 


Stack for temporary strings 


□ □E4- 


•□□27 


3b-3q 


Utility pointer area 


□ □5fl- 


□ DEC 


AU-AA 


Product area for multiplication 


□ □5D- 


■□□2E 


AS-Ah 


Pointer: start-of-BASIC (for 








Bank 0) 


□ □BF- 


■□□3^ 


A7-Aa 


Pointer: start-of-variables 








(Bank 1) 


□ □31- 


■□□32 


A^-SD 


Pointer: start-of-arrays 


□ □33- 


■UU3A 


51-52 


Pointer: end-of-arrays 


□ □35- 


■□□3t 


53-54 


Pointer: string-storage (moving 



down) 



216 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 




Decimal 


Description 


□ D37- 


□ □3fl 


55-5b 


Utility string pointer 


oaaq- 


■□□3a 


57-5fl 


Pointer: limit-of-memory 








(Banl< 1) 


□ □3B- 


■□□3C 


5q-tD 


Current BASIC line number 


□ □3D- 


•□□3E 




Textpointer: BASIC work point 


□ □3F- 


■QUAQ 


ys-yA 


Utility Pointer 




■UDAS 


t5-tt 


Current DATA line number 


□ □^3- 


■QOAA 


t7-tfl 


Current DATA address 




■□□<t 


tq-7a 


Input vector 


□ 


■QQA& 


71-72 


Current variable name 




■UDAh. 


73-74 


Current variable address 


OUAB- 


■nuAC 


75-7t 


Variable pointer for FOR/NEXT 




■UUAE 


77-7fl 


Y-save; op-save; BASIC pointer 








save 


□ □^F 




7<=\ 


Comparison symbol 








accumulator 


□ □5D- 


-□□55 


fl^-flS 


Miscellaneous work area, 








pointers, and so on 


□ □5t- 


-□□5fl 


flt-flfl 


Jump vector for functions 


□□5q- 


-□□EdE 


flq-qfl 


Miscellaneous numeric work 








area 


□ □t3 




qq 


Accum#1 : exponent 




-□□t7 


1^^-1D3 


Accum#1 : mantissa 


□□ta 




IQA 


Accum#1: sign 






1^5 


Series evaluation constant 








pointer 




-□□tF 


l^b-111 


Accum#2: exponent, and so on 


□□?□ 




112 


Sign comparison, Acc#1 versus 








#2 


0D71 




113 


Accum#1 lo-order (rounding) 


□ D72- 


-□□73 


114-115 


Cassette buffer len/Series 








pointer 


□ □74- 


-□□75 


llfc-117 


Auto line number increment 


□ □7t 




llfl 


Graphics flag 


□ □77 




iiq 


Color source number 


□ □7fl- 




12^-121 


Temporary counters 


□□7a- 


-□□7C 


125-124 


DS$ descriptor 


□ □7D- 


-□□7E 


155-lSt 


BASIC pseudo-stack pointer 


QQ&A 




132 


Multicolor 1 (1) 


□ □fl5 




133 


Multicolor 2 (2) 



APPENDIX C — COMMODORE 128 



277 







Decimal 


uGscnpuon 


□□at 




13A 




Graphic foreground color (13) 


□ 




lAA 




Status word ST 






IAS 




Keyswitch lA: STOP and RVS 










flags 


□ □•=15 




lAh 




Timing constant for tape 


nn^A 




1A& 




Serial output: deferred 










character flag 






lA^ 




Serial deferred character 


DDH? 




151 




Rogister sdve 


□ □Sfl 




152 




How manv nnpn filp^ 


ODRR 




153 




Inmit rip\/icp nnririAllv/ H 

II i|JLii U9vi\/C) iiuiiiiciiiy \J 


□ □Hft 




154 




Outnut OMD Hpvirp nnrmallv ^ 

\./ui|>/ui Vi/iviL^ uwviv^Oj iiuiiiiciiiy w 


ODRB- 




155- 


-15ti 


Tnnp nflHtw oi itni it-rpppi\/pH 










ffaa 


□ □qD 




157 




I/O iTiPQQAnPQ' — all 










ti^=6rrors n = nil 

tJ ^ ^1 1 Wl 0, LJ 1 III 


u Lj n ij 


LI LJ n X 


15fl- 


-15R 

M _J 1 


Tonp prrrtr nointorc 

I a\JKS CIIUI jJvlllLOlO 


□ □an- 

LJ LJ n LJ 


-nn A? 

LJ LJ n ^ 


ItD- 


-ItE 


.liffv/ ninrk HMI 

uiiiy wivwiv niviL. 


□ □ft3- 


□ DAB 


JI O -J 






□ DAC- 


■□OAD 


175- 


■173 


Pnintpr* tanp huffpr ^prollinn 

1 VII 1191 ■ iCl|i^o UUIIwl) OwlWIIIIIU 


□ □AE- 


•DDAF 


174- 


•175 


Tanp pnri arlri^/Fnd nf nrnnrain 

■ m|m/9 91 IU CllJlJO/ IU \Jl UIWMIGllll 


□ □BD- 


■ODBl 


17t- 


■177 


Taoe timino constants 


ODBa- 


■□□B3 


17a- 


■17R 


Pointer' start of tanp huffpr 

1 Wll ILwl ■ wlCtl i wl ICIUv UUIId 


DDB7 




las 




Number of characters in file 

I I ■ WV^I Wl IW»I WtWlwl III 1 II W 










name 


□ DBA 




16A 




Current logical file 


□ DBS 




las 




Current secondary address 


OQBA 




Iflb 




Current device 

VI 1 1 \^ III V 1 


ODBB- 


■□□BC 


167- 


•laa 


Pointer to file name 

1 will Iwl iw 1 llw 1 ICil 1 Iw 


□ DBD- 


■00C5 


laq- 


•1^7 


1/0 worl< pointers 


□ DCt- 


□ DC? 


iRa- 


•iqq 


Banks: I/O data, filename 


□ □Cfl- 


•QDCB 


EQQ- 


•ED3 


RS-232 input/output buffer 










addresses 


□ □cc- 


□ OCD 


^DA- 


ED5 


Keyboard decode pointer (Banl< 










15) 


□ □CE- 


□ OCF 


2Db- 


ao7 


Print string work pointer 


□ □DD 




EQ& 




Number of characters in 










keyboard buffer 


QODl 








Number of programmed chars 



waiting 



218 MACHINE LANGUAGE FOR COMMODORE MACHINES 



nsx 




Decimal 


uescnpuon 


□ DDE 








Programmed key character 
index 


□ DD3 




511 




Key shift flag: □ = no shift 


□ □D^ 




5ia 




Key code: 88 if no l<ey 


□ 0D5 




213 




Key code: 88 if no l<ey 


□ □Dt 




214 




Input from screen/from 
keyboard 


ODD? 




215 




40/80 columns: □ = 40 columns 


□ □Dfl 




21t> 




Graphics mode code 


□ DDI 




21? 




Character base: D = ROM, 
4 = RAIVI 


DDDA- 


DDDF 


21fi- 


223 


Misc work area 


DDEQ- 


ODEl 


224- 


225 


Pointer to screen line/cursor 


□ □E2- 


DDEB 


EEb- 


227 


Color line pointer 






22a 




Current screen bottom margin 


LJ LJ XJ -J 




22"=l 




Current screen top margin 


□ □Et 




23D 




Current screen left margin 


DDE? 




231 




Current screen right margin 


DDEfl- 


DDEq 


232- 


233 


Input cursor log (row, column) 


DDEA 




234 




End-of-iine for input pointer 


DDEB 




235 




Position of cursor on screen 
line 


DOEC 




23t> 




Row where cursor lives 


DDED- 


□ □EE 


23?- 


■23fl 


Maximum screen lines, columns 


DDEF 




23q 




Current I/O character 


DDFD 




24D 




Previous character printed 


DDFl 




241 




Character color 


DDF3 




243 




Screen reverse flag 


DDF4 




244 




D = direct cursor; else 
programmed 


DGF5 




245 




Number of INSERTS 
outstanding 


DOFt 




24t 




255= Auto Insert enabled 


DDF? 




24? 




Text mode lockout 


DOFfl 




24fl 




D = Scrolling enabled 


DDFq 




24q 




Bell disable 


DDFA- 


□ DFF 


25D- 


255 


Not used 


□ IDD- 


□ IFF 


25t- 


511 


Processor stack area 


OlDD- 


D13E 


25t- 


31fl 


Tape error log 



APPENDIX C — COMMODORE 128 



219 



Hex 




Decimal 


Description 


UJ U. LI LJ 


LJ L- n LI 


515 


-b75 


BASIC inDut buffer 

ur^^^i^y II ii^ui uui iwi 


LJL.nL— 


■ □P AE 

LJ L. n ij 


h7A 




Bank nppk subroutine 


Lf n i. 


U L~ U U 


tfl7 


-7D1 


Rrink nnkp ^iihrnutinp 


LJ t JJ JJ 


■ UPCC 

LJ t ^ 


7UE 


-71b 


Rank nnmnarp Qiihrnutinp 

LJCll iT\ wWI 1 lla/Cll w OUUIWUIIIIC 




U C JJ IZ 


717 


-73fl 


.I5^R tn annthpr hank 


U t U J 


LJ U. X JJ 


73'^ 


-7t)3 


.IMP tn annthpr hank 

UIVII L\J Cll Iwll Id Udl lr\ 






7t< 


-7t5 


Fiinr^tinn pypputP hnnk 

^*|/ ^ ^ 1 LI J 


ninri- 

LJ -J LJ LI 


LI -J LJ JJ 


7tfl 


-7t'^ 


^rrnr mp^Qanp link 

^1 1 LJI 1 1 ICOOQMw III lr\ 


rr^n?- 

LI J LI L. 


LI J LI J 


770 


-771 


RA5^in warm ^tart link 

ur^oi V-/ vvcii 1 1 1 oicii I III ir\ 


LI J LJ ^ 


LJ J LI J 


775 


-773 


Crunrh RA5^IC tnkpn^ link 

ui ivi 1 ujrwjt\j i\Ji\vi lo III ii\ 


Q3Uh- 


D307 


774 


-775 


Print tokens link 

1 1 11 li Iw III lf\ 


Q3U&- 


D30R 


77Ea 


-777 


Start new BASIC code link 

i 1 IwVV L^rAWI^y wWUw III li\ 


Lf J LI n 


LI -J U U 


77fl 


-771 


f^pt arithmptir pipmpnt link 

V^vl mI III II 1 IwLIV/ wlwlllwlll III ll\ 


LI J LI 


LI J LI 


730 


-7fll 


Orunrh FF hook 

\yi UI Iwl 1 1 ^ 1 IWf\ 


□ 3DE- 


□ 3DF 


755 


-7fl3 


List FE hook 

^Iwl 1 ^ 1 lwUI\ 


□ 31D- 


□ 311 


7&A 


-7fl5 


Fypouta FE hook 


□ 313- 

LJ ^ M Im. 


□ 313 


7&h 


-7fl7 


LJnuspd 

\Jl 1 LiO^\J 


Q31A- 


0315 


76e> 


-76"=! 


IRQ vector fFAtSl 


□ 31t- 


0317 


7R0 


-711 


Break interrunt vector FBCin^l 


LJ -J JJ LI 


LI J JJ 1 


7'^5 


-713 


NMI intprriint vprtor fFA^ni 

I^IVII II HOI 1 LI|.Jl VwL^lLJI [X n ^ LJ J 


□ 31A- 


031B 

LJ _J JJ U 


7'=\A 


-715 


OPEN Vector FEFBDl 


□ 31C- 


031D 


7Rt 


-717 


CLOSE vector FFlflfll 

^^^^^W^ V-wwlwl 1 X JI LJ UJ 


031E- 

LJ _J JJ 0-1 


n3iF 

LJ 1 ^ J. 


7^5 


-711 


Rpt-innrjt vprtnr rFiriPil 

Wd II l|JLIL VCL^ILJI [X JJ LJ nj 


n3?n- 

LI J ^ LJ 


□ 3P1 

LJ — J ^ JJ 


flOD 


-fl^l 


5^pt-ONtnut vprtor FFIi^Pl 

Wwl L/Ull<^UL VwwlWI [X XI ^ 


LJ J t ^ 


n3P3 

LJ J ^ J 


fl05 


-603 


Rp^torp l/n \/prtor FFPPtil 

riCOlUiw l/w VCOIL/I [X L. DJ 


LI J ^ *n 


n3P^ 

LJ J Urn J 


flD4 


-fl05 


Inntit vprtnr rFFfirnl 

IIIULIl VCL^ILJI L LI uJ 


□ 3Et- 


LJ 1^ 1 


ant 


-flD7 


Outnut vprtnr FEF?^! 

Vi^Ul^Lil Vv/wlVJI l,XJ X 1 IJ 


□ 3Efl- 


□ 3ER 


flOfl 


-ADR 


Test-STOP Vector TFttEl 

1 CO I W 1 ^^1 V vvlvl 1 X D D ^ J 


□ 3EA- 


□ 3EB 


fllO 


-All 


GET vector FEEEBl 


LJ _J l_ 


□ 3PD 

\-l —J \— Ly 


fll5 


-fll3 


Abort I/O vertor FFPPPl 


□ 32E- 


035F 


&IA 


-fll5 


Machine Lang Monitor link 


□ 33D- 


□ 331 


filt 


-fll7 


LOAD link 


D33e- 


0333 


fiia 


-an 


SAVE link 


□ 334- 


□ 335 


fiEQ 


-flEl 


Control code (low) link 


□ 33t- 


□ 337 


fl55 


-fl35 


High ASCII code link 


□ 33fl- 


□ 33q 


fl54- 


-fl55 


ESC sequence link 


□ 34A- 


□ 353 


&AE 


-351 


Keyboard buffer 


0354- 


□ 35D 


fl55- 


-fltl 


Tab stop bits 


□ 35E- 


□ 3bl 


at,5- 


-flt5 


Line wrap bits 



220 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Bank 0: 



Hex 




Decimal 


Description 


LJ -J □ ^ 


LI J D U 


LI u □ LI 1 ^ 


Lnniml filp tahip 




LI J 1 ^ 


LI 1 □ LI LI ^ 


r)p\/irp niimhpr t^hlp 




•n37P 

LI _J 1 X 


LJ LJ □ LJ n ^ 


RpponHprv aHHtpqc tAhIp 


U J LJ u 


LI J I Xj 


LI n o n ^ □ 


HHRfiFT mihrniitinp 


□ 3flt 




ROE 


CHRGOT entrv 


□ 3RF- 


■D3AR 


RE7-'13a 


Fetch from RAM Bank 

1 W i W 1 1 II III 1 1 1 V 1 ^^l>4l 1 |\ ^/ 


LJ ^ n u 


LJ .J U O 


R3R-R5D 


Fetch from RAM Bank 1 


□ 3B7- 


■D3BF 




Fetch from RAM Bank 1 


□ 3CD- 


•03Ca 




Fetch from RAM Bank 


U J 1 


\J 3 U Ji 


pfnCi— q77 


F^trh frnm RAM RanW 


LI -J 1^ ^ 


LJ U 1/ ^ 


R7 A-q AD 

n 1 LI n LJ LI 


[ IniiQPH 


U -J 1/ Z3 




q Ai. 

n LI ^ 


CJiirrpnt RANK for <?Y9 PFFK 


LJ -J J-l Li 




qq4 


Granhin/Tpxt harknrnunriQ 

\Jti CI|<Ji iiv/ 1 CAl liyClL/i\MI wUi lUO 


u J ri J 




~ n J 


^rsnhi^/Mi liti r^oinr Inn 
ci|ji iiwiviuiii ouiUi luy 


J. X LI u 




D ^ ^ LJ U 


MMI I pnnfini irfltinn rpniQfpr 

IVIIVIL^ L/UI III^LJI ClliLJI 1 IC^lOlv?! 


X X LI -U 


± X LI ^ 


t5Efll-t5Efl4 


MMLI load cnnfin reaistpr^ 


LI *n LI U 


LI 1 J-l 1 


XILI^^ ^LIL.^ 


4.0-rnlijmn ^rrppn mpmorv 

V/U 1 LI 1 1 1 1 1 Owl C^l 1 1 1 Iwl 1 l\Jl y 




U f X X 


I^IJ*~ILJ t^Ll^i 


^nritp idpntitv flrPA ^tpvt^ 

W|<^l lie ILlwl iiiiy Cll cci yicAiy 


nflnri- 

LI LI U LJ 


LJ 1 X X 


pnz A_pqt,n 


RA55IO n^Pudo-Qtank 


nnnr 




pq7P 

^ ^ 1 L. 


OA A 1 intpmint Inn 

Wlr^ 1 II lid I U^l 


□ ADD 

LI n LI J-/ 




E573 


CIA 1 timer enabled 

\i/lfl 1 til I Iwl wl lUh^lwVI 


LJ n LI X 


t_i n jj 1 


5575-E5fi3 

^ — 1 1 J ^ ^ LI ^ 


RS-232 work values 


□fiifl 




E5fl4 


RS-232 receive Dointer 


LI n jj n 




pq Aq 

^ ^ LI ^ 


RS-Pf^P innut nnlntpr 

1 ivJ ^\J^ III^Ul ^WilllUI 


□ filA 




Esat 


RS-232 transmit pointer 


□ filB 




E5a7 


RS-232 send pointer 


□ AID- 


•OAIF 


E5aa-E5qo 


Sleeo countdown" 








FFFF = disable 

X X X X UlwQUIw 


U rl Li 




pqqp 

C J 1 L. 


Kpvhnard huffpr ^i7p 

IXwyl^L^ClIU ia^LJIld Ol^v7 


n fl p 1. 

U n C Jl 




c ^ n J 


.Qcrppn frpP7P flan 


□ fl55 




Esq^i 


Key repeat: 1 E a = all, 








t< =none 


□ flE3 




Esqs 


Key repeat timing 


□ A2< 




Esqt 


Key repeat pause 


□ AEB 




S5q7 


Graphics/text toggle latch 


□ RPt 




S5qa 


40-col cursor mode 


□ fi27- 


□ REa 


Esqq-EfcDE 


40-col blink values 


OfiEB 




EtD3 


80-col cursor mode 


□ fiEC 




EbD< 


40-col video $DDia image 



APPENDIX C — COMMODORE 128 



221 



Hex 




Decimal 


Description 




-□ASF 




-5tD7 


80-coI pages — screen, color 


□ fi^D 


-□ftSfi 


Eb5< 


-5b50 


40/80 pointer swap $EO-Fa 


□ AbO 


-□AtD 




-EtfcH 


40/80 data swap $354-3tl 


□acD 




5752 




PAT counter 


□ ACl 


-□AC< 


5753 


-575fc 


ROM Physical Address Table 


□ BDO 


-□BBF 


5filb 


-3007 


Cassette buffer 


OCOG 


-□DFF 


3075 


-3533 


RS-232 input, output buffers 


□EDD 


-□FFF 


3534 


-40q5 


System sprites ( 5 1 - 1 3 ) 




-IDQq 


4oqt 


-4105 


Programmed key lengths 


IDDA 


-IDFF 




-4351 


Programmed key definitions 


lino 


-1130 


<355 


-4400 


DOS Command staging area 


1131 


-llbE 


AAUl 


-44t5 


Graphics work area 


lltF 








Trace mode: FF=on 


117D 


-1173 




-44b7 


Renumbering pointers 


117^ 


-1177 


AAhd, 


-4471 


Directory work pointers 


117fl 


-11H7 


AA7E 


-4473 


Graphics index 


117a 


-117B 


AAIA 


-4475 


Float-fixed vector [34 RF] 


117C 


-117D 


AA7\3 


-4477 


Fixed-float vector [7R3C] 


117E 


-11D5 


AAlb 


-45ti5 


Sprite motion tables (8x11 










bytes) 


llDb 


-11E5 


45tt 


-4531 


Sprite X/Y positions 


llEt 




4535 




Sprite X-high positions 


11E7 


-llEfl 


4533 


-4534 


Sprite bump masks (sprite, 










backgnd) 


llER 


-llEA 


4535 


-453t 


Light pen values, X and Y 


llEB 




4537 




CHRGEN ROM page, text [DB] 


llEC 




4538 




CHRGEN ROM page, graphics 










[DO] 


llED 




45Bq 




Secondary address for 










RECORD 


llEE 


-IIFF 


45qo 


-4t07 


Unused 


lEUA- 


-1E07 


4tl5 


-4bl5 


PU characters ( / . $) 


1506- 


-ISDC 


4tlR 


-4b5D 


TRAP address: F FFF if none 


lElD- 


-lEll 


4t54 


-4b55 


End of BASIC 


iei5- 


-1513 


4t5b 


-4t,57 


Basic program limit [FFOO] 


1E14- 


-1S17 


4b5B- 


-4t31 


DO work pointers 


151fl- 


-lElfi 


4t35- 


-4t34 


USR program jump [7D5B] 


151B- 


-151F 


4t35- 


-4t3q 


RND seed value 


1E5E 




4t45 




Sound tempo 


laEF 




4t55 




Music sequencer 



222 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Hex 



Decimal 



Description 



Bank 1 : 

0^00- 
Bank 14: Same as 
DDDD- 

Bank 15: 

DDOO- 
DADD- 
D5DD- 



1EB7 Ai,i.D-Ai,y3 Note image 

1E3E AhL5-Ai,7Q Current env pattern 

1E7D <t71-<7en Envelope tables .. 

Ah71-Ah&Q AD(SR) pattern 

1552 <tfll-<tqD (AD)SR pattern 

1E5C <tqi-<70D Waveform pattern 

lEtb <7D1-';;71D Pulse width pattern 

1E70 ^711-^720 Pulse widtli hi pattern 

1E74 Note: xx.xx.volume 

4 7 E 5 Previous volume image 

lE7a <7Eb-47Efl Collision IRQ task table 

1E7E A7?'^-A73A Collision IRQ address tables 

4735 Collision mask 

473b Collision work value 

47 as PEN work value 

A&kA-LlAB Unused 

tl44-71fc7 Reserved for key functions 

71bfl-fc4511 BASIC RAM memory (text) 

71ta-fllflfc Video (color) matrix (hi-res) 

aia7-aiqi Sprite identities (hi-res) 

aiq5-lt3a3 Screen memory (hi-res) 

Ib3a4-b4511 BASIC RAM memory (hi-res) 

Basic variables, arrays, strings 

Character generator ROM 

ROM: BASIC 
40-col videa chip 8564 
SID sound chip 6581 
Memory Management Unit 
8722 

DfcOO-DtDl 547a4-547a5 80-column CRT controller 8563 
DaD0-DaE7 55EHt-5tEq5 Color nibbles 
DCDD-DCDF 5t3ED-5fc33t CIA 1 (IRQ) 6526 
DDDD-DDDF 5t57fc-5t5qi CIA 2 (NMI) 6526 
DFDQ-DFDR 57Daa-570qa DMA slot 
EDOO-FEFF 57344-t5E7q ROM: Kernal 
FFD5-FFFF b5Ea5-t5535 ROM: Transfer, Jump Table 



1E34- 
lE3q- 
1E3F- 
1E3F- 

1E53- 

1E5D- 

lEb7- 

1E71- 

1E75 

lE7b- 

lE7q- 

1E7F 

lEao 

ISBl 
13DD- 

laoD- 

ICDO 

ICDD- 

IFFB- 

EDOD- 

4D00- 



17FF 
IBFF 
FBFF 
1FF7 
IFFF 
3FFF 
FBFF 

FBFF 
Bank 15, 
DFFF 

CFFF 
DOEE 
D41C 
D50A 



lDE4-b4511 
below, except: 
53E4a-57343 

It3a4-53E47 
53E4a-53Eq4 
54E7E-543DD 
545Ea-5453fl 



APPENDIX C — COMMODORE 128 



223 



8502 Processor I/O registers 



0000 


xxxxx 


0=in 


1=out 


= in 


1=out 


1=out 


1=out 


1=0lll 


00000 


0001 


xxxxx 


Caps 
Key 


Tape 
Motor 


Tape 
Sense 


Taps 
Outpt 


HiRes 


LoRes 


Color 
Acces 


00001 



Figure CIS 



224 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



CI 28 Memory Map 
8564 Video — Sprite Registers 



Sprite 


Sprite 






Sprite Sprite 





7 






7 


0000 


DOOE 


Position 


X_ 


53248 53262 


D001 


OOOF 




Y 


53249 53263 


0027 


D02E 


Color 


53287 53294 



Sprite Bit Positions 
7 6 5 4 3 2 1 



001 


X-position liigh 


53264 


O015 


Sprite Enable 


53269 


0017 


Y-expand 


53271 


001 B 


Bacl<ground Priority 


53275 


001 C 


i\^uiticoior 


53276 


0010 


X-expand 


53277 


001 E 


interrupt: Sprite coiiisn 


53278 


001 F 


interrupt: Sprite/Bacl<grd coil 


53279 



Figure C.I 6 



APPENDIX C — COMMODORE 128 



225 



C128 Memory Map 



D011 
D012 
D013 
0014 





8564 Video — 


Control and Misc. Registers 






Extnd Color 


Bit Map 


Dsply EnabI 


Row Selct . 

A 


Y-Scroll 








Raster Register 










Light Pen Input 


X 
Y 



S3265 
53266 
53267 
53268 



D016 


X 


Reset 


Multi Color 


Colm Sel . 

A 


X-Scroll 


53270 
















D018 


Screen (Video Matrix) 
vm13 vm12 vm11 


vm10 


Character Base 
cb13 cb12 cb11 


X 


53272 


D019 


IRQ 


IRQ sence 




LP 1 SSC 1 SBC 


RST 


53273 


D01A 


IRQ Enable 




Light Collision 
Pen , Sprt , Back 


Rastr 


53274 



COLOR REGISTERS 



0020 














Exterior 


53280 


0021 














Bacl(ground #0 


S32B1 


0022 














Background #1 


53282 


0023 














Background #2 


53283 


0024 














Background #3 


53284 


0025 














Sprite Multicolor #0 


53285 


O026 














Sprite Multicolor #1 


53286 


D02F 


xxxxx 


xxxxx 


xxxxx 


xxxxx 


xxxxx 


[Keyboard Rows] 


53295 


0030 


xxxxx 


xxxxx 


xxxxx 


xxxxx 


xxxxx 


xxxxx 


Test 


Fast 
Clock 


53298 



Figure C.I 6 continued 



226 MACHINE LANGUAGE FOR COMMODORE MACHINES 



SID (6581) Commodore 128 



V1 
U40U 

D401 


V2 


V3 








VI V2 V3 


U4U/ 

D408 


U'fUt 
D40F 


— Frequency 


1 

H 


<^4^>79 *;497Q 'i4.Pftfi 

54273 54280 54287 


D402 


D409 


D410 


Pulse Width 


L 


54274 54281 54288 


D403 


D40A 


D411 







H 


54275 54282 54289 


D404 


D40B 


D412 


Voice Type 

NSE 1 PUL 1 SAW 1 TRI 




KEY 

1 1 1 


54276 54283 54290 


D405 


D40C 


D413 


Attacl< 
Time 

2ms-8sec 

1 1 1 




Decay 
Time 

6ms-24sec 
1 1 1 


54277 54284 54291 


D406 


D40D 


D414 


Sustain 

level 

1 1 1 




Release time 

6ms-24sec 
1 1 1 


54278 54285 54292 



Voices 
(write only) 



D415 





L 


54293 


D416 


Filter Frequency 


H 


54294 


D417 


Resonance F'"®'' voices 

, , , |eXT, V3 , VJ , V, 


54295 


D418 


Passband 

V3 1 

OFF 1 HI 1 BD 1 LO 1 


Master 

Volume 

1 1 1 


54296 



Filter & Volume 
(write only) 



D419 Paddle X 54297 

D41A Paddle Y 54298 

D41B Noise 3 (random) 54299 

D41C I Envelope 3 ~| 54300 

Sense 
(read only) 

Special voice features (TEST, RING MOD, SYNC) are 
omitted from the above diagram. 

Figure C.17 



APPENDIX C — COMMODORE 128 227 



Memory Management Unit 8722 



DSOO 


RAM select 
0-3 


HIGH RAM 
/ROM 


MID RAM 
/ROM 


LO 
RAM 


CGEN 


54S28 


DS01 
-D504 


Preconfiguratlon registers; 
Similar to DSOO, above 


54529 
-54532 


D50S 


40/80 
Key 


C64 
Mode 


Cartr-Sense 
Color-Bank 


Fast 
Disk 


xxxxxxxxxxx 


280 


54533 


D506 


Video-Bank 


xxxxxxxxxxx 


Shared RAM 
hi knv 


Shared RAM 
1K 


54534 


D507 
D508 


L 

H 




Zero page pointer 
($0000) 








54535 
54536 


D509 
D50A 


L 
H 




Stack page pointer 
($0100) 








54537 
54538 



Figure C.I 8 



228 MACHINE LANGUAGE FOR COMMODORE MACHINES 



8563 CRT Controller 



D600 read (status): 



D800 


Status 


Ught 
Pen 


Vert 
Blank 


xxxxxxxxxxxxxxxxxxxxxxxxx 


54784 








D600 
54784 


□601 
54785 


Value 


$00 


Horizontal Total 


126 


1 $01 


Horizontal Characters Displayed (80) 


80 


2 $02 


Horizontal Sync position 


102 


3 $03 


Sync WIdtli 

Vertical Horizontal 


1/3 


4 $04 


xxxxx 1 Vertical Total 


32 or 39 


5 $05 


xxxxx xxxxx xxxxx 1 Vertical Total Adjust 





6 $06 


xxxxx 


Vertical Displayed (25) 


25 


7 $07 


xxxxx 


Vertical Sync Position 


29 or 32 


8 $08 


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 


Interlace 





9 $09 


xxxxxxxxxxxxxxxxx 


Scan Lines per Character 


7 


10 $0A 


xxxxx 1 Cursor Mode 


Cursor Start 


32 


1 1 $0B 


xxxxxxxxxxxxxxxxx 


Cursor End 


7 


12 $0C 

13 $0D 


xxxxxxxxxxx 


Display H 
Address L 








14 $0E 

15 $0F 


Cursor Address H 

L 






16 $10 

17 $11 


Light Pen H 
Input L 


varies 
varies 


18 $12 

19 $13 


Video RAM Address H 
(See register 31) L 


varies 
varies 


20 $14 

21 $15 


Color H 
Address L 


B 



22 $16 


Character 
Total C 


)isplay Horizontal 
Display Vertical 


120 
g 


23 $17 


xxxxxxxxxxxxxxxxx 




24 $18 


Blocl< 
Copy 


Born 
RVS 


Blink 
Rate 


V Scroll 


32 


25 $19 


Bit 
Map 


Color 
Enable 


Semi 
Graphic 


Wide 
Pixel 


H Scroll 


64 or 71 


26 $1A 


Color 

Foreground Background 


240 


27 $1B 


Scroll Control Horizontal 





28 $1C 


Char set address 


RAM 1 xxxxxxxxxxxxxxxx 


32 


29 $1D 


xxxxx xxxxx xxxxx 


Underline Scan Line Count 


7 


30 $1E 


Character Count 


varies 


31 $1F 

32 $20 

33 $21 


Video RAM data (see registers 18,19) 


varies 

varies 
varies 


Block Copy Start H 
Address L 


34 $22 

35 $23 


Display begin 
Enable end 


125 
100 


36 $24 


xxxxxxxxxxxxxxxxxxxxxx 1 DRAM refresh rate 


S 



Figure C.19 



APPENDIX C — COMMODORE 128 



229 



CIA 1 (IRQ) (6526) Commodore 128 





Paddle SEL 
A , B 








R 1 


Joystick 
L , D 


1 u 




$DCOO 


Keyboard Row Select (Inverted) 


PRA 56320 














Joystick 1 




$DC01 






Keyboard Column Read 








PRB 56321 


$DC02 








$FF — 


All Output 








DDRA 56322 










$00 — 


All Input 










UUnb ODOfO 


!pUuU4 
$DC05 








Timer A 










TAL 56324 
TAH 56325 


$DC06 
$DC07 








Timer B 










TBL 56326 
TBH 56327 
























$DCOC 


Serial (shift) Register 


56332 


$DCOD 


IRQ 


xxxxxxxxxxx 


Rag 


S.Reg 


xxxxx 


TIm.B 


Tlm.A 


56333 


$DCOE 




S Reg 
I/O 








Timer A 
ToggI 








56334 






Load 


0/S 






Start 


$DCOF 












Timer B 








56335 








Load 


0/S 






Start 



Figure C.20 



230 MACHINE LANGUAGE FOR COMMODORE MACHINES 



CIA 2 (NMI) (6526) Commodore 128 



$DDOO 


Serial 
In 


Clock 
In 


Serial 
Out 


Clock 
Out 


ATN 
Out 


1 1 

RS-232 
Out 


1 1 

Video 


Block 


PRA 


56576 


$DD01 


DSR 
In 


CTS 
In 






DCD* 
In 


Rl* 
In 


DTR 
Out 


RTS 
Out 


RS-232 
In 


PRB 


56577 










Parallel User Port 












$DD02 


In 


In 


Out 


Out Out 
$3F 


Out 


Out 


Out 


DDRA 


56578 


$DD03 


$06 For RS-232 


DDRB 


56579 


$DD04 
$DD05 










Timer A 










TAL 

TAH 


56580 
56581 


$DD06 
$DD07 










Timer B 










TBL 
1 bn 


56582 
56583 




























$DDOD 




RS-232 
In 




Timer 
B , 


Timer 
A 


ICR 


56589 


$DDOE 


Timer 
, A Start 


CRA 


56590 


$DDOF 


Timer 
, B Start 


CRB 


56591 



Figure C.21 



DMA Controller 



DFOO 


Busy 


Fault 


xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx 


57088 


DF01 


Exec 


Sum 


xxxxxxxxxxx 


IRQ 


Inc 


Mode 


57089 


DF02 






Host 




L 


57090 


DF03 






Address 




H 


57091 


DF04 






Expansion 




L 


57092 


DF05 






Address 




H 


57093 


DF06 


xxxxxxxxxxxxxxxxxxxxxxxxxxxxx 


Expansion Bank 


57094 


DF07 






Transfer 




L 


57095 


DF08 






Length 




H 


57096 


DF09 


Checksum 


57097 


DFOA 


Version, MaxImum-IVIemory 


57098 



xxxx = unused 
(blank) = not of interest 



Figure C.22 



APPENDIX C — COMMODORE 128 



231 



Commodore 64: ROM Detail 

This type of ROM memory map is intended primarily for users who want 
to "browse" through the inner logic of the computer. It allows a user to 
disassemble an area of interest, to see why the computer behaves in a 
certain way. With the use of this map, the user will be able to identify 
subroutines that are called by the coding under study. 

I recommend against using the ROM subroutines as part of your own 
programs. They often don't do precisely what you want. They change 
locations when you move to a different machine. With rare exceptions, 
you can probably write better coding to do the job yourself. Stick with the 
kernal jump table: especially $FFDa to output; $FFE4 to get input; 
$FFE1 to check the RUN/STOP key; $FFCfc and $FFCR to switch 
input and output respectively; and $FFCC to restore normal input/output. 
They are the same on all Commodore computers. 

aODO : ROM control vectors 

ft □ □ C : Keyword action vectors 

ft □ 5 2 : Function vectors 

A □ fl □ : Operator vectors 

ROSE: Keywords 

RIRE: Error messages 

ft 3 E a : Error message vectors 

ft 3 Ea 5 : Miscellaneous messages 

ft3flft : Scan stack for FOR/GOSUB 

ft 3 B a : Move memory 

ft 3 F B : Check stack depth 

kAD6: Check memory space 

ft^ 3 5 : Print "out of memory" 

ft^37: Error routine 

ft^tq: BREAK entry 

HAIA: Print "ready . " 

kA&Q: Ready for BASIC 

ft^ SC : Handle new line 

ft533 : Re-chain lines 

ft5 b : Receive input line 

ft57'1: Crunch tokens 

fttl3: Find BASIC line 

ftb<2: Perform [NEW] 

fttSE: Perform [CLR] 

fttaE : Back up text pointer 

fttqC: Perform [LIST] 



232 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Perform [FOR] 

a 7 E D : Execute statement 

RAID : Perform [RESTORE] 

aaec: Break 

RflEF: Perform [STOP] 

Rfl31: Perform [END] 

aa57: Perform [CO NT] 

afl71: Perform [RUN] 

aflflB: Perform [GOSUB] 

aaaO: Perform [goto] 

aflDE: Perform [RETURN] 

aflFfi: Perform [b a T A] 

a'=1 1 : Scan for next statement 

aqafl: Perform [IF] 

aR3B: Perform [REM] 

aq^B: Perform [ON] 

an bB : (3et fixed point number 

aqa5: Perform [LET] 

aaaO: Perform [PRINT#] 

aaat: Perform [CMD] 

aaaO: Perform [print] 

aBlE : Print string from (Y.A) 

aB 3 B : Print format cliaracter 

aB^D : Bad input routine 

aB7B: Perform [GET] 

KBkS: Perform [INPOT#] 

aBBF: Perform [INPUT] 

aBFR : Prompt and input 

aCDt: Perform [RE ao] 

aCFC : Input error messages 

RDIE : Perform [NEXT] 

aD7 a : Type match cfiecl< 

aDRE : Evaluate expression 

aEaa: Constant-pl 

aEFl: Evaluate witliin bracl<ets 

aEF7 : Check for " ) " 

aEFF : Check for comma 

aFOa: Syntax error 

AFIA : Check range 

aF 2 a : Search for variable 

aFR7 : Set up FN reference 

aFEfc: Evaluate [OR] 



APPENDIX C — COMMODORE 1 28 233 



RFEq: Evaluate [AND] 

BDlfc: Compare 

BDfll: Perform [DIM] 

B □ a B : Locate variable 

B 1 1 3 : Check alphabetic 

BHD: Create variable 

B 1 R 4 : Array pointer subroutine 

BIAS: Value 3E7ta 

BIBE: Float-fixed 

BlDl: Set up array 

BE AS: Print "bad subscript" 

B a ^ fl : Print "illegal quantity" 

B3AC: Compute array size 

B37D: Evaluate [F RE] 

B3R1: Fixed-float 

B3qE: Evaluate [POS] 

B3fit: Checl< direct 

B3B3: Perform [DEF] 

B3E1: Checl< fn syntax 

B3F4 : Evaluate [FN] 

BAhS: Evaluate [ST R$] 

BA7S: Calculate string vector 

B^fi?: Set up string 

BAFA: Make room for string 

B 5 E t : Garbage collection 

B 5 B D : Check salvageability 

BhDh: Collect string 

Bti3D: Concatenate 

B 1 7 ft : Build string to memory 

Btft3 : Discard unwanted string 

BtDB : Clean descriptor stack 

BfcEC: Evaluate [CHR$] 

B7 00: Evaluate [LEFT$] 

B7 2C: Evaluate [RIGHT$] 

B737: Evaluate [MID $] 

B7bl : Pull string parameters 

B77C: Evaluate [L EN] 

B7 a E : Exit string-mode 

B7aB: Evaluate [AS C] 

B 7 R B : Input byte parameter 

B7AD: Evaluate [?AL] 

B7EB : Parameters for POKE/WAIT 



234 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



B7F7: 


Float-fixed 


BfiDD: 


Evaluate [PEEK] 


BflE< : 


Perform [POKE] 


BflED: 


Perform [WAIT] 


Bfl^R: 


Add □ . 5 


BflBD: 


Subtract-from 


Bfl53: 


Evaluate [subtract] 


BflbA: 


Evaluate [add] 


B^A7 : 


Complement FAC (floating accumulator)*! 


BS7E: 


Print "overflow" 


Bqfl3: 


Multiply by zero byte 


B^ER: 


Evaluate [LOG] 


BAEB: 


Evaluate [multiply] 




Multiply-a-bit 


BRflC: 


Memory to FaC#E 


BRB7: 


Adjust Fac#l and FaC#S 


BAD<: 


Underflow/overflow 


BAEE: 


Multiply by 1 □ 


BAPq: 


+ 1 □ in floating point 


BRFE: 


Divide by ID 


BBIE: 


Evaluate [divide] 


BBRE 


: Memory to FAC#1 


BBC7 


: FRC#1 to memory 


BBFC 


: FRC#E to FRC#1 


BCDC 


: FRC#1 to FRC#S 


BCIB 


: Round FAC#1 


BCEB 


: Get sign 


BC3q 


: Evaluate [SGN] 


BC5fi 


: Evaluate [RBS] 


BC5B 


: Compare FRC#1 to memory 


BCqB 


: Float-fixed 


BCCC 


: Evaluate [INT] 


BCF3 


: String to FRC 


BD7E 


: Get ASCII digit 


BDCE 


: Print "IN.." 


BDCD 


: Print line number 


BDDD 


: Float to ASCII 


BFlt 


: Decimal constants 


BF3A 


: TI constants 


BF71 


: Evaluate [SQR] 


BF7B 


: Evaluate [power] 


BTBA 


: Evaluate [negative] 



APPENDIX C — COMMODORE 128 235 



Dr riU . 


bvaiuate L'C>a1:'J 


£1 U A d . 


Series evaluation 1 


1? n c Q • 


Series evaluation E 


T? n a *7 • 


tvaiuate [kndj 


JiUr n . 


Kernal calls with error checking 




rertorm [SYSJ 


£1 Jj 3 b . 


renorm [oAVrij 




rerform [VERIrij 


171 C- A • 


rerrorm liiUiiiJj 


17 1 m7 • 
£iJiD£i . 


rertorm lUriiNj 


£iJjL r . 


rertorrn [CLObEj 


171 T\/' • 


rararneters lor LUAU/oiiVrii 


17 3 n C- • 
£iCUb . 


Check default parameters 


17 3 rrp • 


Check for comma 


17 3 1 □ • 


Parameters for open/close 


IT 3 t_ /■ • 


evaluate [LUbj 


17 3 r D • 


evaluate [bi Nj 


3 K y • 


evaluate [TAN] 




evaluate lATNj 


1737R • 


vvarm resian 


17 3 Q y* • 


Initialize 


3 7\ 3 • 

Jcid Ac : 


c tin GET tor zero page 


"C 3 D17 • 


Initialize basic 




Vectors for $ 3 


P /■ C 3 • 

riH 3 d . 


Initialize vectors 


17/" C17 • 


Power-up message 


17 q n n • 

£1 3 U U . 


vaet i/u aaoress 


17 c n c • 

£i3U3 . 


Get screen size 


pen n • 

£1 3 U ti . 


rui/gei row/coiumn 


17 C 1 A - 


Initialize l/U 


17 C /" /" • 


Clear screen 


17 c: L L • 
£1 3 b b . 


nome cursor 


P C (L P • 
£1 3 b L . 


Set screen pointers 


17 C 7\ n - 

£i b U . 


bet i/u detauits 


JJ ^ U *-| • 


Inniit frr»m I^A\/Kr\orH 
lll[JUl IIUIil ISc^yUQafU 


Eb3E: 


Input from screen 


ELfl^ : 


Quote test 


Etqi : 


Set up screen print 


EbBb : 


Advance cursor 


EtED : 


Retreat cursor 


E701: 


Back into previous line 



236 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



E 7 1 1 : Output to screen 

Efi7C: Go to next line 

EflU: Perform (return) 

EfiRl: Check line decrement 

EflBB: Check line increment 

EflCB: Set color code 

E fl D a : Color code table 

EflER: Scroll screen 

ERtS: Open space on screen 

ERCfl : Move a screen line 

Synchronize color transfer 

E =1 F □ : Set start-of-line 

EHFF : Clear screen line 

EA13: Print to screen 

EA54 : Synchronize color pointer 

Ea31 : Interrupt-clock, etc. 

Eaa?: Read keyboard 

E B 7 ■=! : Keyboard select vectors 

E B fi 1 : Keyboard 1 -unshifted 

E B C 2 : Keyboard 2-shifted 

ECD3 : Keyboard 3-"Commodore" shift 

'ECAA: G raphics/text contrl 

E C ^ F : Set graphics/text mode 

EC7fl: Keyboard 4 

ECBH : Video chip setup 

ECE7 : Shift/run equivalent 

ECFD : Screen In address low 

EDDR: Send "talk" to serial bus 

EDDC : Send "listen" to serial bus 

□ : Send to serial bus 

EDBE: Serial timeout 

EDBR: Send listens a 

EDBE : Clear aTN 

EDC7: Send talks a 

EDCC : Wait for clock 

EDDD : Send serial deferred 

EDEF : Send "untalk" to serial bus 

EDFE : Send "unlisten" to serial bus 

EE13 : Receive from serial bus 

EEflB: Serial clock on 

EEflE: Serial clock off 

EEq7: Serial output "1" 

EEaD: Serial output "0" 



APPENDIX C — COMMODORE 128 



237 



EEfiR : 


oc^iial III aiiu olUUK olynalS 


EEB3 : 


Dplflv/ 1r miIIiQPr»nnrl 
L^^icty ju 1 1 11 1 iioc7\/Ui lU 


J— I -LJ U Lj ■ 




EFOt : 


fipnrl npu/ RQ-P'^P h\/to 


EF5E : 


Nn-D 9 R prrnr 

INU i-/ O IV ClIUI 


EF31 • 


I^HJ ^ X O OllUl 


EF3B • 


r^icsKIp timpr 
L^iodUlc? llllim 


EF<fl : 


Comnutp hit rnunt 


EF5R : 


no ^Oi£. fCyUclVc 


RF7F • 

U i. 1 U • 


oci U|J lu iC/Uc^lVc 


EFC5 : 


Rpppiwp naritv/ prrnr 


EFCR : 


Rppipwp n\/prflA\A/ 
ricVi/icvc uvciiiuw 


EFCD : 


Rpppi\/p Krpsil^ 
nci^dvc uiccif\ 


FFnn • 


nidiiiiiiu ciiui 


EFEl : 


Submit to RS-232 


Fnnn • 

1. LJ LJ X/ • 


INU JJ O Ja ciiUi 


r u jj r > 


QpnH tn DQ OQO hnff^^r 
OcllQ lO riO'dO^ DUUQT 


FD^D : 


Inniit frnm RQ-OQO 
iii|jui iiuiii no jco^ 


FOflt : 


Get from R55-P'^P 

Vi^wl II \J* II 1 iw 


FOAA : 


Gheok ^prifll hii^ IHIp 

wl lwwf\ O^l ICli k/UO ILIIC? 


FDBD : 


Messaops 


FIEB: 


Print if direct 

1 1 II 1 1 ■ ■ Villi W \J I 


F13E : 


Get 


Fl^^E : 


from 

• • • II Ul 1 1 1 


F157 : 


Inni it 


Fiqq • 


tnPt' tartp/cprial/QQ.O'^O 


FlCft : 


Outniit 


FIDD : 


tn tsnp 


FEDE : 


^pt inniit Hp\/ipp 


FE50 : 


Sst outnut ripvirp 


FERl : 


ninQP flip 

wiWOC IIIC7 


F30F : 


Find filp 

1 II lU 1 1 1 w 


F31F: 


Set file values 

^^\^ ^ III V W^l U V'W ' 


F35F : 


Abort all filp^ 

fiwwl I will iliww 


F333 : 


Rp^torp HpfAiilt I/O 


F3^ft: 


Do file ooen 

lll\^ ^^I^V^I 1 


F3D5 : 


Send SA 


F40q: 


Open RS-232 


F4SE: 


Load program 


FSftF: 


Print "searching" 


F5C1: 


Print filename 


F5Da: 


Print "loading/verifying" 


F5DD: 


Save program 



238 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



FbfiF : 


Print "saving" 


Ft'lB : 


Bump clocl< 


FtBC : 


Log PI a l<ey reading 


FbDD : 


Get time 


FtE4 : 


Set time 


FtED : 


Ciieci< stop key 


FfcFB : 


Output error messages 


F72D : 


Find any tape header 


F7bR : 


Write tape header 


F7DD : 


Get buffer address 


F7D7 : 


Set buffer start/end pointers 


F7ER : 


Find specific header 


FflDD : 


Bump tape pointer 


Ffil7 : 


Print "press play . . ." 


FflSE : 


Checl< tape status 


Ffl3fl : 


Print "press record . . ." 


Ffl^l : 


Initiate tape read 


Fflt^ : 


Initiate tape write 


Ffl75 


Common tape code 


FflDO 


Check tape stop 


FflEE 


; Set read timing 


FREC 


: Read tape bits 


FftbD 


: Store tape characters 


FBflE 


: Reset pointer 


FBR7 


: New character setup 


FBat 


: Send transition to tape 


FBCfl 


: Write data to tape 


FBCD 


: IRQ entry point 


FC57 


: Write tape leader 


FCH3 


: Restore normal IRQ 


FCBfl 


: Set IRQ vector 


Fcca 


: Kill tape motor 


FCDl 


: Check R/W pointer 


FCDB 


: Bump R/W pointer 


FCE2 


: Power reset entry 


FDDE 


: Check fl-ROM 


FDin 

L 1/ ^ LJ 


fi-ROM mask 


FD15 


: Kernal reset 


FDia 


: Kernal move 


FD3a 


: Vectors 


FD5D 


: Initialize system constants 


FDqB 


: IRQ vectors 


FDa3 


: Initialize I/O 



APPENDIX C 



— COMMODORE 128 



23d 



FDDD 


: Enable tirner 


FDFR 


: Save filename data 


FEDO 


: Save file details 


FED? 


Get status 


FElfl 


: Flag status 


FEIC 


: Set status 


FE51 


: Set timeout 


FE25 


Read/set top of memory 


FE27 


Read top of memory 


FEED 


Set too of msmorv 


FE34 


Read/^et bottom of memorv 


FE<3 


NMI entry 


FEtt 


Warm start 


FEBt 


Reset IRO and exit 


FEBC 


InterruDt exit 

ill fcwl 1 Mil/ I V«/\l 1 


FEC5 


RS-232 timing table 


FEDt 


NMI RS-232 in 


FFQ7 


NMI RS-232 out 




Fake IRQ 


FF^fl 


IRQ entry 


FFfll 


Jumbo jump table 


FFFA 


: Hardware vectors 



D 



Character 
Sets 



241 



242 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Superchart 

The "superchart" shows the PET character sets. A byte may have any of 
several meanings, depending on how it is used. The chart is constructed 
to reflect this. "ASCII" is PET ASCII; these are the characters as they 
would be input or printed. "Screen" is the Commodore screen codes, as 
they would be used in screen memory— POKE ing to or PEEKing from 
the screen would yield these codes. Notice that the numeric character set 
is the same for both screen and PET ASCII. 

Within a program, the code changes again. "BASIC" shows these codes; 
they are similar to ASCII in the range $ED to $5F. 

Machine language op codes are included for the sake of convenience and 
completeness. 



DECIMAL 


HEX 


ASCII 


SCREEN 


BASIC 


6502 


DECIMAL 





00 




@ 


end-line 


BRK 





1 


01 




A 




ORA(l,X) 


1 


2 


02 




B 






2 


3 


03 




C 






3 


4 


04 




D 






4 


5 


05 


white 


E 




ORAZ 


5 


6 


06 




F 




ASLZ 


6 


7 


07 


bell 


G 






7 


8 


08 


locl< 


H 




PHP 


8 


9 


09 


unlock 


1 




ORA# 


9 


10 


OA 




J 




ASLA 


10 


11 


OB 




K 






11 


12 


OC 




L 






12 


13 


OD 


car ret 


M 




ORA 


13 


14 


OE 


text 


N 




ASL 


14 


15 


OF 


top 









15 


16 


10 




P 




BPL 


16 


17 


11 


cur down 


Q 




ORA(l),Y 


17 


18 


12 


reverse 


R 






18 


19 


13 


cur home 


S 






19 


20 


14 


delete 


T 






20 


21 


15 


del. line 


U 




ORA Z,X 


21 


22 


16 


ers.begin 


v 




ASL Z,X 


22 


23 


17 




w 






23 


24 


18 




X 




CLC 


24 


25 


19 


scr. up 


Y 




CRAY 


25 


26 


1A 




z 






26 


27 


IB 




[ 






27 


28 


1C 


red 


\ 






28 


29 


ID 


cur right 


1 




ORAX 


29 



APPENDIX D — SUPERCHART 



243 



ECIMAL 


HEX 


ASCII 


SCREEN 


BASIC 


6502 


DECII 


30 


1E 


green 


T 




ASLX 


30 


31 


IF 


blue 








31 


32 


20 


space 


space 


space 


JSR 


32 


33 


21 


! 


! 


1 


AND(I,X) 


33 


34 


22 


It 


" 


" 




34 


35 


23 


# 


# 


# 




35 


36 


24 


$ 


$ 


$ 


BITZ 


36 


37 


25 


% 


% 


% 


ANDZ 


37 


38 


26 


& 


& 


& 


ROLZ 


38 


39 


27 


, 


f 


f 




39 


40 


28 


( 


( 


( 


PL 


40 


41 


29 


) 


) 


) 


AND# 


41 


42 


2A 


* 


* 


* 


ROLA 


42 


43 


2B 


+ 


+ 


+ 




43 


44 


2C 


1 


■ 


1 


BIT 


44 


45 


2D 











AND 


45 


46 


2E 








ROL 


46 


47 


2F 


/ 


/ 


/ 




47 


48 


30 











BMI 


48 


49 


31 


1 


1 


1 


AND(I),Y 


49 


50 


32 


2 


2 


2 




50 


51 


33 


3 


3 


3 




51 


52 


34 


4 


4 


4 




52 


53 


35 


5 


5 


5 


AND Z,X 


53 


54 


36 


6 


6 


6 


ROL Z,X 


54 


55 


37 


7 


7 


7 




55 


56 


38 


8 


8 


8 


SEC 


56 


57 


39 


9 


9 


9 


ANDY 


57 


58 


3A 








CLI 


58 


59 


3B 










59 


60 


3C 


< 


< 


< 




60 


61 


30 


_ 


— 


- 


ANDX 


61 


62 


3E 


> 


> 


> 


ROLX 


62 


63 


3F 


? 


? 


? 




63 


64 


40 


@ 


B 


@ 


RTI 


64 


65 


41 


A 


1, a 


A 


EOR(l,X) 


65 


66 


42 


B 


m, b 


B 




66 


67 


43 


C 


S,c 


C 




67 


68 


44 


D 


e, d 







68 


69 


45 


E 


B,e 


E 


EORZ 


69 


70 


46 


F 


B.f 


F 


LSRZ 


70 


71 


47 


G 


U.g 


G 




71 


72 


48 


H 


n, h 


H 


PHA 


72 


73 


49 


1 


Q, i 




EOR# 


73 


74 


4A 


J 


13. j 


J 


LSRA 


74 


75 


4B 


K 


H, k 


K 




75 


76 


4C 


L 


m 


L 


JMP 


76 


77 


4D 


M 




M 


EOR 


77 


78 


4E 


N 


la, n 


N 


LSR 


78 



244 MACHINE LANGUAGE FOR COMMODORE MACHINES 



DECIMAL 


HEX 


ASCII 


SCREEN 


BASIC 


6502 


DECI 


79 


4F 





Co 







79 


80 


50 


P 


P 


P 


BVC 


80 


81 


51 


Q 


1, q 


Q 


EOR(l),Y 


81 


82 


52 


R 


B. r 


R 




82 


83 


53 


S 


ffl, s 


S 




83 


84 


54 


T 


Ct 


T 




84 


85 


55 


U 


Q, u 


U 


EOR, Z,X 


85 


86 


56 


V 


H, V 


V 


LSR Z,X 


86 


87 


57 


w 


P. w 


w 




87 


88 


58 


X 


1. X 


X 


CLI 


88 


89 


59 


Y 


y 


Y 


EOR Y 


89 


90 


5A 


z 


1, z 


z 




90 


91 


5B 


[ 


m 


[ 




91 


92 


5C 


\ 


B 


\ 




92 


93 


5D 


] 




] 


EORX 


93 


94 


5E 


T 


a, s 


T 


LSRX 


94 


95 


5F 


«— 




«- 




95 


96 


60 




□ 




RTS 


96 


97 


61 




n 




ADC(I,X) 


97 


98 


62 




B 






98 


99 


63 




□ 






99 


100 


64 




□ 






100 


101 


65 




D 




ADCZ 


101 


102 


66 








RORZ 


102 


103 


67 




□ 






103 


104 


68 








PLA 


104 


105 


69 




EM 




ADC# 


105 


106 


6A 




□ 




ROR A 


106 


107 


6B 










107 


108 


6C 




a 




JMP(I) 


108 


109 


6D 




s 




ADC 


109 


110 


6E 




a 




ROR 


110 


111 


6F 




a 






111 


112 


70 




s 




BVS 


112 


113 


71 




H 




ADC(I),Y 


113 


114 


72 




a 






114 


115 


73 




m 






115 


116 


74 




c 






116 


117 


75 




D 




ADC Z,X 


117 


118 


76 




a 




ROR Z,X 


118 


119 


77 




□ 






119 


120 


78 




n 




SEI 


120 


121 


79 




□ 




ADCY 


121 


122 


7A 










122 


123 


7B 




□ 






123 


124 


7C 




a 






124 


125 


7D 




H 




ADCX 


125 


126 


7E 




B 




RORX 


126 


127 


7F 




IS 






127 



APPENDIX D — SUPERCHART 



245 



DECIMAL 


HEX 


ASCII 


SCREEN 


BASIC 


6502 


DECI^ 


128 


80 




r-@ 


END 




128 


129 


81 


orange 


r-A 


FOR 


STA(I,X) 


129 


130 


82 




r-B 


NEXT 




130 


131 


83 




r-C 


DATA 




131 


132 


84 




r-D 


INPUT# 


STYZ 


132 


133 


85 




r-E 


INPUT 


STA Z 


133 


134 


86 




r-F 


DIM 


STX Z 


134 


135 


87 




r-G 


READ 




135 


136 


88 




r-H 


LET 


DEY 


136 


137 


89 




r-l 


GOTO 




137 


138 


8A 




r-J 


RUN 


TXA 


138 


139 


8B 




r-K 


IF 




139 


140 


8C 




r-L 


RESTORE 


STY 


140 


141 


8D 


car ret 


r-M 


GOSUB 


STA 


141 


142 


8E 


graphic 


r-N 


RETURN 


STX 


142 


143 


8F 


bottom 


r-0 


REM 




143 


144 


90 


black 


r-P 


STOP 


BCC 


144 


145 


91 


cur up 


r-Q 


ON 


STA(I), Y 


145 


146 


92 


rvs off 


r-R 


WAIT 




146 


147 


93 


clear 


r-S 


LOAD 




147 


148 


94 


insert 


r-T 


SAVE 


STYZ,X 


148 


149 


95 


ins. line/br 


r-U 


VERIFY 


STA Z,X 


149 


150 


96 


ers. end/p 


r-V 


DEF 


STX Z,Y 


150 


151 


97 


Gray 1 


r-W 


POKE 




151 


152 


98 


Gray 2 


r-X 


PRINT# 


TYA 


152 


153 


99 


scr. down 


r-Y 


PRINT 


STA Y 


153 


154 


9A 


L. Blue 


r-Z 


CONT 


TXS 


154 


155 


9B 


Gray 3 


r-[ 


LIST 




155 


156 


9C 


magenta 


r-\ 


CLR 




156 


157 


9D 


cur left 


r-] 


CMD 


STA X 


157 


158 


9E 


yellow 


r-t 


SYS 




158 


159 


9F 


cyan 


r-*- , 


OPEN 




159 


160 


AO 




■ 


CLOSE 


LDY # 


160 


161 


A1 


C 


r-l 


GET 


LDA(I,X) 


161 


162 


A2 


H 


{-" 


NEW 


LDX # 


162 


163 


A3 


n 


r-# 


TAB( 




163 


164 


A4 


□ 


r-$ 


TO 


LDYZ 


164 


165 


A5 


□ 


r-% 


FN 


LDA Z 


165 


166 


A6 


s 


r-& 


SPC( 


LDX Z 


166 


167 


A7 


□ 


r-' 


THEN 




10/ 


168 


A8 




r-( 


NOT 


TAY 


168 


169 


A9 


B. & 


r-) 


STEP 


LDA# 


169 


170 


AA 


□ 


r-* 


+ 


TAX 


170 


171 


AB 


IE 


r- + 






171 


172 


AC 


a 


r-, 


* 


LDY 


172 


173 


AD 


H 


r- 


/ 


LDA 


173 


174 


AE 


S 


r-. 


T 


LDX 


174 


175 


AF 


a 


r-/ 


AND 




175 


176 


BO 


Q 


r-O 


OR 


BCS 


176 



246 MACHINE LANGUAGE FOR COMMODORE MACHINES 



DECIMAL 


HEX 


ASCII 


SCREEN BASIC 


6502 


DECIMAL 


177 


B1 


H 


r-1 


> 


LOA(l),Y 


177 


178 


B2 


S 


r-2 


= 




178 


179 


B3 


m 


r-3 


< 




179 


180 


B4 


c 


r-4 


SGN 


LOY Z,X 


180 


181 


B5 




r-5 


INT 


LOA Z,X 


181 


182 


B6 


□ 


r-6 


ABS 


LDX Z,Y 


182 


183 


B7 


n 


r-7 


USR 




183 


184 


B8 


n 


r-8 


PRE 


CLV 


184 


185 


B9 


□ 


r-9 


POS 


LOA Y 


185 


186 


BA 


a, 


r-; 


SQR 


TSX 


186 


187 


BB 


a 


r-; 


RND 




187 


188 


BC 


a 


r-< 


LOG 


LOYX 


188 


189 


BD 


ffl 


r- = 


EXP 


LOAX 


189 


190 


BE 


D 


r-> 


COS 


LDX Y 


190 


191 


BF 


B 


r-? 


SIN 




191 


192 


CO 


B 




TAN 


CPY# 


192 


193 


CI 


k, a 




ATN 


CMP(I),X 


193 


194 


C2 


m, b 




PEEK 




194 


195 


C3 


8. c 




LEN 




195 


196 


C4 


e. d 




STR$ 


CPYZ 


196 


197 


C5 


H, e 




VAL 


CMPZ 


197 


198 


C6 


a, f 




ASC 


DECZ 


198 


199 


C7 


DD, g 




CHR$ 




199 


200 


C8 


DD, h 




LEFT$ 


INY 


200 


201 


09 


S, i 




RIGHTS 


CMP # 


201 


202 


CA 






MID$ 


DEX 


202 


203 


CB 


ffl, k 




GO 




203 


204 


CC 


D, 1 




CONCAT 


CPY 


204 


205 


CD 


IS, m 




OOPEN 


CMP 


205 


208 


CE 


Z, n 




DOLOSE 


DEC 


206 


207 


CF 


n, 




RECORD 




207 


208 


DO 


a.p 




HEADER 


BNE 


208 


209 


D1 


1, q 




COLLECT 


CMP(I),Y 


209 


210 


D2 


g, r 




BACKUP 




210 


211 


D3 


1, s 




COPY 




211 


212 


D4 


n, t 




APPEND 




212 


213 


05 


Q, u 




DSAVE 


CMP Z,X 


213 


214 


06 


H, V 




OLOAD 


DEC Z,X 


214 


215 


07 


1, w 




<^ ATA 1 rt/^ 

CATALOG 




215 


216 


D8 


H, X 




RENAME 


CLO 


216 


217 


09 


□l.y 




SCRATCH 


CMP Y 


217 


218 


DA 


l.z 




DIRECTORY 




218 


219 


08 


m 








219 


220 


DC 


E] 








220 


221 


bo 


n 






CMP X 


221 


222 


OE 


s, a 






DEC X 


222 


223 


OF 




i 






223 


224 


EO 








CPX# 


224 


225 


El 




Li 




SBC(I).X 


225 



APPENDIX D — SUPERCHART 



247 



DECIMAL 


HEX 


ASCII 


SCREEN BASIC 


i5502 


DEC! 


226 


E2 




C3 




226 


227 


E3 




■ 




227 


228 


E4 




■ 


CPX Z 


228 


229 


c5 




■ 


SBC Z 


229 


230 


E6 




n 

m 


INC Z 


230 


231 


E7 




■1 
■1 




231 




CO 
CO 




B 


INX 


232 


233 


E9 




B. m 


SBC # 


233 








■I 


NOP 


234 


235 


CD 
CD 




D 




235 




cU 






CPX 


236 




cU 




li 


SBC 


237 


OOO 

Zoo 


BC 

cc 




■■ 

P 


INC 


238 


00& 


cc 
cr 




B 




239 


Oil A 


rU 




D 


Bed 


240 


0>l 4 


C4 
Pi 




El 


SBC(I), Y 


241 


o>io 


CO 




H 




242 


OilO 

243 


CO 

r3 




'.a 




243 


Oil il 

244 


p4 




n 




244 


Oyl C 

240 


ro 




rm 

n 


Sou Z,X 


245 


240 


Cfi 

ro 




W 


INC Z,X 


246 


247 


F7 




1 




247 


248 


F8 




i 


BED 


248 


249 


F9 




H 


SBC Y 


249 


250 


FA 




l.B 




250 


251 


FB 




9 




251 


252 


FC 




B 




252 


253 


FD 




B 


SBCX 


253 


254 


FE 




a 


INCX 


254 


255 


FF 




IB IT 




255 



248 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Control Character Representations 



NUL 


Null 


DLE 


Data Link Escape (CC) 


SOH 


Start of Heading (CC) 


DC1 


Device Control 1 


STX 


Start of Text (CC) 


DC2 


Device Control 2 


ETX 


End of Text (CC) 


DCS 


Device Control 3 


EOT 


End of Transmission (CC) 


DC4 


Device Control 4 


ENQ 


Enquiry (CC) 


NAK 


Negative Acknowledge (CC) 


ACK 


Acknowledge (CC) 


SYN 


Synchronous Idle (CC) 


BEL 


Bell 


ETB 


End of Transmission Block 


BS 


Backspace (FE) 




(CC) 


HT 


Horizontal Tabulation 


CAN 


Cancel 




(FE) 


EM 


End of Medium 


LF 


Line Feed (FE) 


SUB 


Substitute 


VT 


Vertical Tabulation (FE) 


ESC 


Escape 


FF 


Form Feed (FE) 


FS 


File Separator (IS) 


-» CR 


Carriage Return (FE) 


GS 


Group Separator (IS) 


SO 


Shift Out 


RS 


Record Separator (IS) 


SI 


Sfiift In 


US 


Unit Separator (IS) 






DEL 


Delete 


(CC) 


Communication Control 






(FE) 


Format Effector 






(IS) 


Information Separator 







Figure D.I 



Special Graphic Characters 



^SP 


Space 


-» < 


Less Than 


I 


Exclamation Point 


— > = 


Equals 


-»" 


Quotation Marks 


-» > 


Greater Than 


^# 


Number Sign 




Question Mark 


^$ 


Dollar Sign 




Commercial At 


^% 


Percent 


->[ 


Opening Bracket 


-»& 


Ampersand 


\ 


Reverse Slant 


1 


Apostrophe 


^] 


Closing Bracket 


^( 


Opening Parenthesis 




Circumflex 


^) 


Closing Parenthesis 




Underline 


. * 


Asterisk 




Grave Accent 




Plus 


{ 


Opening Brace 




Comma 


1 


Vertical Line (This graphic 




Hyphen (Minus) 




is sometimes stylized to 




Period (Decimal Point) 




distinguish it from the un- 




Slant 




broken Logical OR which 




Colon 




is not an ASCII character) 


» 


Semicolon 


} 


Closing Brace 








Tilde 



Characters marked -» correspond to the PET ASCII character set. 
Figure D.2 



APPENDIX D — ASCII 



249 



ASCII 

ASCII is the American Standard Code for Information Interchange. It is 
the standard for communications, and is often used with non-Commodore 
printers. 

When a Commodore machine is in its graphic mode, its character set 
corresponds closely to ASCII. Numeric, upper case alphabetic, and punc- 
tuation characters are the same. A few control characters, such as 
RETURN, also match. Commodore graphics have no counterpart in ASCII. 

When the Commodore machine is switched to text mode, the character 
set diverges noticeably from ASCII. Numeric characters and much of the 
punctuation corresponds, but ASCII upper case alphabetic codes match 
the Commodore computer's lower case codes. Commodore's upper case 
alphabetics are now completely out of the ASCII range, since ASCII is a 
seven-bit code. 

As a result. Commodore's PET ASCII codes require conversion before 
transmission to a true ASCII device or communications line. This may be 
done with either hardware interfacing or with a program. Briefly, the pro- 
cedure is: 

1 . If the Commodore character is below $ 3 F , it may be transmitted directly to 
the ASCII facility. 

2. If the Commodore character is between S-^ D and $5F, it should be logically 
OEed with $BD (or add decimal 35) before transmission to ASCII. 

3. If the Commodore character is between $00 and $DF, it should be logically 
RNDed with $7F (or subtract decimal lEfl)before transmission to ASCII. 

Equivalent rules can be derived to allow a Commodore computer to receive 
from ASCII. For either direction of transmission, some control characters 
may require special treatment. 



250 MACHINE LANGUAGE FOR COMMODORE MACHINES 



First Hexadecimal Digit 



(0 








1 


2 


3 


4 


5 


6 


7 





NUL 


DLE 


SP 





@ 


P 




P 


1 


SOH 


DC! 


! 


1 


A 


Q 


a 


q 


2 


STX 


DC2 




2 


B 


R 


b 


r 


3 


ETX 


DC3 


# 


3 


C 


S 


c 


s 


4 


EOT 


DC4 


$ 


4 


D 


T 


d 


t 


5 


ENQ 


NAK 


% 


5 


E 


U 


e 


u 


6 


ACK 


SYN 


& 


6 


F 


V 


f 


V 


7 


BEL 


ETB 


t 


7 


G 


w 


g 


w 


8 


BS 


CAN 


( 


8 


H 


X 


h 


X 


9 


HT 


EM 


) 


9 


1 


Y 




y 


A 


LF 


SUB 


* 




J 


z 


j 


z 


B 


VT 


ESC 


+ 


t 


K 


( 


k 


{ 


C 


FF 


FS 




< 


L 


\ 


1 


1 
1 


D 


CR 


GS 






M 


] 


m 


} 


E 


SO 


RS 




> 


N 




n 




F 


SI 


US 


/ 


? 










DEL 



ASCII code values. 



E 

Exercises for 
Alternative 

Commodore 
IVIacliines 



251 



252 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Commodore 128 users should turn to page 257. 

From Chapter 6: 

VIC-20 (Unexpanded) Version 

We write the BASIC program as follows: 

!□□ V%=0 

IIU F0RJ = 1T0 5 

12D INPUT "VALUE" 

130 SYS + + + + 

IAD PRINT "TIMES TEN =" 

150 NEXT J 

Plan to start the machine language program at around <0R7 + 127,or 
AEEA (hexadecimal IQflO). On that basis, we may change line 130 to 
SYS 4 E 54. Do nof try to run the program yet. 



A loao 


LDY 


#$05 




a lOflE 


LDA 


($5D) , 


Y 


A IQ&A 


STA 


$033C 




A IDfi? 


STA 


$D33E 




A lOfiA 


LDY 


#$03 




A lOflC 


LDA 


($5D), 


Y 


A loaE 


STA 


$033D 




A loqi 


STA 


$D33F 




A loq^ 


ASL 


$033D 




A lOq? 


ROL 


$033C 




A loqA 


ASL 


$D33D 




A ID^D 


ROL 


$D33C 




A lOAO 


CLC 






A lOAl 


LDA 


$D33D 




A 10A4 


ADC 


$033F 




A IDA? 


STA 


$D33D 




A IDAA 


LDA 


$033C 




A lOAD 


ADC 


$D33E 




A lOBO 


STA 


$□330 




A 10B3 


ASL 


$033D 




A lOBL 


ROL 


$0330 




A IGBR 


LDY 


#$□5 




A IGBB 


LDA 


$0330 




A IDBE 


STA 


($5D) , 


Y 


A IDCO 


LDY 


#$□3 




A iDca 


LDA 


$033D 




A 1DC5 


STA 


($5D), 


Y 


A 10C7 


RTS 







APPENDIX E — PET/CBM VERSION 



253 



To change the start-of-variables pointer to a location above the machine 
language program, display the SOV pointer with .M DDSD DDEE and 
change the pointer to 

:DDED Cfl ID 

PET/CBM Version 

We write the BASIC program as follows: 

!□□ V^=D 

110 F0RJ = 1T0 5 

150 INPUT "VfiLUE" 

130 SYS + + + + 

IAD PRINT "TIMES TEN = " ; 

150 NEXT J 

Plan to start the machine language program at around lDS5 + 127,or 
1155 (hexadecimal <flO). On that basis, we may change line 130 to 
SYS 1155. Do noMry to run the program yet. 



A 


O-^flO 


LDY 


#$05 




A 




LDA 


($5A), 


Y 


A 


DA&A 


STA 


$033C 




A 


UA&7 


STA 


$D33E 




A 


UA&k 


LDY 


#$03 




A 


UA&C 


LDA 


($5A), 


Y 


A 


OA&B 


STA 


$033D 




A 


o^qi 


STA 


$033F 




A 


o<q/; 


ASL 


$033D 




A 


o^q? 


ROL 


$033C 




A 


D^qA 


ASL 


$033D 




A 


D^qD 


ROL 


$D33C 




A 


D^AO 


CLC 






A 


O^Al 


LDA 


$033D 




A 


O^A^ 


ADC 


$033F 




A 


0<A7 


STA 


$033D 




A 


D^AA 


LDA 


$033C 




A 


O^AD 


ADC 


$033E 




A 


O^BO 


STA 


$033C 




A 


QAB3 


ASL 


$D33D 




A 


D<Bt 


ROL 


$033C 




A 


D^eq 


LDY 


#$05 




A 


D^BB 


LDA 


$033C 




A 


D^BE 


STA 


($5A), 


Y 



254 MACHInI language FOR COMMODORE MACHINES 



ft QACD LDY #$03 
A DACE LDft $D33D 
ft QiSGS STft ($EA),Y 
ft Qi^C? RTS 

To change the start-of-variables pointer to a location above the machine 
ikhguage program, display the SOV pointer with M DDSft DDSB and 
change the pointer to 

iDUEk Cfl D< . . 

From Chapter 7: 

An Interrupt Project 

VIC-20 (Unexpanded) Version 

The only difference with the VIC-20 is that the screen is located at $ IE □ □ : 

ft D33C LDft $qi 
ft 033E STft $1EDD 
A Q3A1 JMP ($D3ftD) 

To place the link address into $D3ftD/l: 

ft niAA LDft $Q31A 
ft Q3A7 STft $03ftD 
ft 034ft LDft $0315 
ft 034D STft $03ftl 

To fire up the program: 

ft 0350 SEI 

ft 0351 LDft #$3C 

ft 0353 STft $0314 

ft 035t LDft #$03 

ft d35fl STft $0315 

ft 035B CLI 

ft D35C RTS 

To restore the original interrupt: 

A D35D SEI 
ft D35E LDA $03AD 
A D3tl STA $0314 
A D3Ed4 LDA $03A1 
A D3t7 STA $0315 



APPENDIX E — PET/CBM VERSION 



255 



A dafcft CLi 

a 03tB RTS 

SYS fl3t will Invoke the new Interrupt code; SYS flbl will turn it off. As 
with the Commodore 64, there is a possibility of the character printing 
white-on-white, so that it cannot be seen. 



PET/CBM Version 

This version is not for original ROM machines, which have the IBQ vector 
located at address SDEl'^/A: 

a 0330 LDa $qB 

a □33E STa $flDDD 

a nsAi JMP ($D3aD) 
To place the linl< address into $D3aD/l: 

a niAA LDa SDoqa 

a 03^7 STA $D3Rn 

a D34a LDa $dqri 
a U3AB STa $03ai 

To fire up the program: 

a 0350 SEI 
a 0351 LDa #$3C 
a 0353 STa IDDRD 
a 035^ LDa #$D3 

a 0356 STa $no<=]i 

a 0358 CLI 
a D35C RTS 

To restore the original interrupt: 

a □35D SEI 
a □35E LDa $03aD 
a □3bl STa $OQRD 
a Q3hA LDa $D3ai 

a D3t7 STa $Doqi 
a Q3yA CLI 

a DStB RTS 

SYS fl3t will invoke the new interrupt code; SYS flbl will turn It off. 
Since the PET/CBM does not have colors, the characters will always show. 



256 MACHINE LANGUAGE FOR COMMODORE MACHINES 



1 



Project: Adding a Command 

PETICBM Version 

It's not possible to write a comparable program to add a command to the 
PET/CBM. This machine doesn't have a "link" neatly waiting for us at 
address $030fi/R. Equivalent code would need to be somewhat longer 
and less elegant. 

The equivalent program for PET/CBM won't be given here. It would involve 
writing over part of the CHRGET program (at $□□?□ to $0Dfl7), sup- 
plying replacement cdde for the part we have destroyed, and then adding 
the new features. 



APPENDIX E — EXERCISES FOR THE C128 



257 



Exercises for the Commodore C1 28 

From Chapter 1: 



Locations $0360 and $ 0361 are important in the CI 28. Tiiey are sen- 
sitive BASIC locations, and if we changed them, BASIC would stop worl<- 
ing. So we'll change the task to this: swap the contents of locations $ □ B fl □ 
and $DBfll. 

Our plan will lool< lil<e this: 
LDA $aBfiD (bring in first value) 
LDX $DBai (bring in second value) 
STA $DBfil (store In opposite place) 
STX SDBfiD (and again) 
BRK 

We may write the machine language code as: 

AD fiO DB LDA $DBQO 

AE fll OB LDX $OBfll 

flD fll OB STA SDBfll 

flE flO DB STX $DBflD 

□ BRK 
The code within the computer will consist of 13 bytes: AD flO DB AE fll 
DB flD fll DB flE flD DB DO. Now we decide where to put it. 

On the Commodore 1 28, we can't use the addresses starting at $ □ 3 3 C— 
we'd quici<ly run into sensitive areas. We'll place our program into the 
C128's cassette buffer that starts at address $DBDD (decimal El flit). 
That's a good place to put short test programs on this machine, and most 
of our following examples will go there. 

On the Commodore 128, the BASIC command MONITOR will bring the 
machine language monitor into action. You'll immediately get the register 
display: 

MONITOR 

PC SR AC XR YR SP 

; FBDDD DD DD DD DD Pq 
The cursor will be flashing at the start of the next line. 

The information is as explained in chapter 1 , except that the address under 
PC contains an extra digit. The first digit (in this case, the "F") is called 
Vn^ank number. The letter F is hexadecimal notation for the value 15 
decimal, and we say that the program stopped in bank 15 at address hex 



BDDD. 




258 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



For the moment, we can consider that "bank 15" means "situated in 
ROM— Read Only Memory." We l<now that the iVIachine Language Monitor 
is built into the Commodore 128; so of course it's in ROM. 

When we write programs, we will put them in RAM. The Commodore 128 
has a great deal of RAM fitted to it. We could choose RAM from bankO, 
where BASIC programs are stored, or from bank 1, where BASIC vari- 
ables, arrays and strings are kept. There's plenty of memory in either 
bank. We will choose bank 0, mostly because it's easier— if the first digit 
is zero (for bank 0) we don't have to type it. 

To display memory from $lDDOto$lDlDwe would command: 

M 1000 1010 
The resulting memory display might look something like this: 

>1D0D 07 Dt OA 07 Ob 04 05 Dfl: 

>lDDfl Oq 05 A7 5E Al 50 A& A"^: . .GRAPHI 

>1D1Q A3 AA AC AT Al AA 22 44 :CDLOAD"D 
The four-digit number at the start of each line represents the address in 
memory being displayed. The two-digit numbers to the right represent the 
contents of memory. The characters to the right of the colon are ASCII 
equivalents of the same memory contents (or a period if no equivalent 
exists). If you are working on an 80-column monitor, you will get more 
memory locations per line than are shown above. 

To change memory, we move the cursor until it is positioned over the 
memory contents in question, type over the value displayed, and then 
press RETURN. You can't change the ASCII part of the display; only the 
two-digit hexadecimal values. 

If you have displayed the contents of memory, as in the example above, 
you might wish to change a number of locations. Be careful: on the Com- 
modore 128, this particular part of memory holds the definitions for the 
function keys, F1 to F10. The first ten bytes are definition lengths; the 
following locations, as you might have guessed, are the definitions them- 
selves. If you play with these locations, expect to end up with muddled 
function keys. 

Here comes our final rewrite of this program example: 

DBOO AD flO DB LDA SOBflO 

OBOB AE fil OB LDX $OBfll 

OBOb aD fll OB STA $OBfll 

DBOq fiE flO DB STX $DBflO 

OBOC 00 
Now to put it in: 



APPENDIX E — EXERCISES FOR THE C128 



259 



We go to the MLM, and display memory with 
M BDD BDC 

Note that we may drop leading zeros. The first address in full is □□BDD 
(banl< D, address DBD D). But we may shorten it if we wish; in either case, 
we'll get something like: 

>DDBDD XX XX XX XX XX XX XX XX : 

>DDBDfl XX XX XX XX xx xx xx xx: 

l\^ove the cursor back and change this display so that it looks like this: 

>DDBDD AD flD DB AE ai OB flD fll: 

>DDBDa DB flE flD DB DD XX XX XX : 

Don't type in the "xx" or the trailing colon or periods— just leave whatever 
was there before. And be sure to press RETURN. If you have an 80- 
column display, you will get the whole memory display on one line. 

Now we must put something into locations $DBfiDand$DBaiso that 
we'll know that the swap has taken place correctly. 

Display memory with M BfiD Bfll and set the resulting display so that 
the values are 

>DDBaD 11 R"^ XX XX XX XX xx xx 
Remember to press RETURN. Now we may run our program; we start it 
with 

G BDQ 

Display the data values to confirm that they have been exchanged with 
M 03&0 D361. 



From Chapter 2: 

Print projects: 

The first exercise uses the same code, but is placed in address B^^: 

A DBDD LDA #A& 
Note that the use of the dollar sign for hexadecimal is optional in this 
monitor. It's probably better to use it, but if you don't the computer will 
assume hex numbers are intended. Using the plus sign to signal a decimal 
number, you could type . . .LDA # + 75 and the decimal value of 
7 S — the same value as hex < fi— will be accepted. You could even type 
. . . LDA #^D1DD1DDD to enter the same number in binary. Either 
way, it's still the ASCII letter H, and you'll find that hexadecimal is more 
convenient and compact. 

If you have correctly typed the line, it will be assembled. The object code 
will be placed into memory starting at the address specified and you'll also 



260 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



see it on the screen as part of the line that you originally typed. You'll also 
get a prompt for the next instruction. The screen will now show: 

ft DDBDD Aq ^fl LDfi#$^fl 

ft QDBDS 

The cursor will be flashing to the right of the "5." Continue by typing in 
JSR $FFD5 and pressing RETURN. Again, the computer will rework 
what you have typed and anticipate your next line by printing ft DDBDS, 
which allows you to type in the final command, BBK. The screen now 
looks like this: 

RDDBDDAq^fl LDR #$<fl 

ft QUEUE EU DE FF JSR $FFD2 

ft DDBDB □□ BBK 

ft ODBOb 

Press RETURN to signal that you're finished. If you wish, you may display 
memory with M BDO BOt. You'll see your program in memory: 

>DDBOD ftq 50 DE FF OD xx xx 
There's less need to check your work with a disassembler since you can 
see the code as it is being written. But it never hurts to be safe; so we 
may inspect our program again with: 

D BUU BUS 

Note that we give two addresses, the starting and the ending address. If 
you give the starting address only, you'll get about 20 bytes of code, which 
is more than we need. 

If you wish to disassemble more code than the screen will hold, you may 
"continue" a disassembly by typing the letter D by itself. You'll get about 
20 more bytes from wherever your previous disassembly left off. Inciden- 
tally, you can use the same technique for memory display: an M command 
without an address will continue a memory display. 

Minor errors that you spot in either an assembly or a disassembly may 
be corrected directly on the right-hand side of the assembly or disassembly 
listing. In other words, suppose that you had incorrectly coded LD ft # $ 5 fl 
during the assembly phase; when you perform the disassembly, this line 
will show as 

□ □BDD 5fl LDft#$5fi 
You recognize that the $58 should be $48; you may move the cursor up— 
use cursor home if you wish— and type over the value on the right-hand 
side. In this case, you place the cursor over the 5, type A to change the 
display to and press RETURN. You will see from the display that 
the problem has been fixed. 

To run the program type the command G FDBOD. What? Our program 
is in bank 0; how can we call it by naming bank 15? And why would we 
do so? 



APPENDIX E — EXERCISES FOR THE C128 



261 



We can successfully call the program by naming bank 15 for this reason: 
in bank 15, all addresses below hexadecimal AUDU (decimal lh3&A) 
are taken from RAN, bank 0. It would be more accurate to call bank 15, 
"configuration 15." You can read more on this, when you're ready, in 
Appendix B-1 . That explains how we get there; but why bother? 

We need to call bank 15 because our program calls CHROUT at address 
$FFD5— a ROM routine. And we see ROM in bank 15, not in bank 0. If 
we were in bank and made a subroutine call to address $FFD2, we'd 
jump to RRM at that address. There's no code at that location in RAM, 
and we'd be in trouble. 

When you get into advanced programming in the Commodore 128, you 
will be able to call subroutines across banks. At that time, you'll be able 
to have a program running in bank zero that will call a subroutine in ROM, 
bank 15, with provision for a successful return to bank zero. When you're 
ready for it, you'll find that a subroutine called JSFAR, located at address 
$02CD in all banks, will do the job of getting you across and back. You'll 
need to learn how to carefully set up the contents of addresses E to fl 
before calling JSFAR. 

For the moment, we can skip the advanced techniques and get our pro- 
gram running with G FQBDD. The H will be printed on the same line, to 
the right of the last zero. 

To switch this program to a BASIC-callable subroutine, we must change 
the BRK command at the end to an RTS. Disassemble, if you wish, and 
type over the BRK with the characters RTS. 

Just before returning to BASIC, let's ask for the decimal equivalent to 
hexadecimal QBOD. Type $BDD and press return. You'll see the equiv- 
alent representations in hexadecimal (the same number), in decimal 
( + Efllt) and also in octal and binary. The decimal value E flit is what 
we need. 

Return to BASIC (using the X command). The computer will say READY; 
you may now call your program with a SYS command. 

The computer has told us that address SDBOD is Efllt in decimal. If 
we had forgotten to ask before leaving the ML M, we could now ask BASIC 
with PRINTDECC'QBOO"); we'd get the same value of 5 fl 1 fc printed. 
Now we type BANK15:SYS2fllt. When we press RETURN, the letter 
H will be printed. 

Don't forget the reason that we are using BANK 15— it's to make sure 
that we reach both our program in R AM (below hex < □ □ D) and the Kernal 
ROM (hex 4D0D and above) at the same time to avoid extra "switching" 
work. Now we may type NEW and enter a BASIC program: 



262 MACHINE LANGUAGE FOR COMMODORE MACHINES 



!□□ BANK 15 
IID FOR J = l TO ID 
lED SYS Efllt, 
13D NEXT J 

If you prefer, you're allowed to say SYS DEC( "BDD" ) in line lED. 
BASIC commands know only decimal numbers, so we must translate from 
hex one way or another. 

Loops project: 

a OBUU LDX #□ 

fi DBDS LDfi $BDE,X 

A DBDS JSR $FFDE 

ft DBDa INX 

ft DBOq CPX #t 

ft DBDB BNE $BD2 

ft DBDD RTS 
After entry, the program looks like this: 

ft DBDO Aa □□ LDX#$DQ 

ft OBDS BD DE DB LDA$DBDE,X 

A DBDS 5D D5 FF JSR $FFD5 

ADBDflEfl INX 

AOBOqEODE, CPX#$Dt 

A DBDB DD F5 BNE $0605 

A OBDD bD RTS 
We guessed (or planned) that the address $DBDE would be available for 
our message HELLO. Now we must store these characters in memory. 

Command M BDE BIB, and type over the display to show 

>DOBDE A& AS AC AC AT OD xx xx 
Return to BASIC (with X) and try BANK 15 : SYS EfllL. The computer 
should say HELLO. 

Once again, you may set up a BASIC loop program: 

lOD BANK 15 

IID FOR J = l TO 3 

lED SYS Efllt 

13DNEXTJ 
To preserve the program within DATA statements, type: 

FOR J = 2fllL TO 5a35:PRINT PEEK(J) ; :NEXT J 
Study the above line. You will see that it asks BASIC to go through the 
part of memory containing your machine language program, and display 
the contents (in decimal notation, of course). You'll see a result that looks 
something like this: 

ILE □ laq lA 11 32 210 ess 532 t 

EDfl 5^5 7E bq 7t 7t 7q 13 



APPENDIX E — EXERCISES FOR THE CI 28 



263 



You may arrange these within data statements: 

50 DATA ltS,D,lfiq,l<,ll/3E,210,E55,235,5E4,fc 

tD DATA EDa,545,qt,7E,bR,7t,7t.,7q,13 

flD FOR J = 5fllt TO afl35:READ XrPOKE J,X:NEXT J 

. . . and our program continues as before with: 
IDD BANK 15 
IID FOR J = l TO 3 

150 SYS salt 

13D NEXT J 

From Chapter 3: 

Input exercise: 
A ODBOD JSR $FFE1 
A 00BD3 BEQ $B15 
A QDBD5 JSR $FFE< 
A □□BDfi GMP #30 
A OQBQA BCC $QBOO 
A DDBOC CMP #3A 
A □□BDE BCS $BDO 
A DDBIQ JSR $FFD2 
A DDBIS AND #$DF 
A DDBIS RTS 

The fonvard branch to $ □ B 1 5 was a guess, but it turns out to be correct. 



The final assembly looks like this: 



A 


□ □BDO 


ED 


El 


FF 


JSR 


$FFE1 


A 


□ □BD3 


FO 


ID 




BEQ 


$DB15 


A 


□ □BDE 


EO 


E^ 


FF 


JSR 


$FFE< 


A 


aQBDfl 


cq 


3D 




CMP 


#$3D 


A 


QOBOA 


qn 


TA 




BCC 


$DBDD 


A 


DDBGC 


cq 


3A 




CMP 


#$3A 


A 


ODBDE 


BO 


FD 




BCS 


$DBDD 


A 


□ DBIO 


ED 


DE 


FF 


JSR 


$FFDE 


A 


D0B13 


Eq 


DF 




AND 


#$DF 


A 


□ □B15 


tD 






RTS 





Call the subroutine for testing with BANK 15:SYS 2816. 

From Chapter 4: 

Addition program: 

Be sure that the above code from the previous chapter has been entered 
before continuing with the main program: 
A DDBIL JSR $BDD 



264 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



A 


□ DBiq 


STA 


$Bta 


A 


□ □BIC 


LDA 


#$5B 


A 


□ □BIE 


JSR 


$FFD5 


A 


□ □BEl 


JSR 


SBDD 


A 




TAX 




A 


□ □B55 


LDA 


#$3D 


A 


□ □B27 


JSR 


$FFDE 


A 


□ DBEA 


TXA 




A 


QDBEB 


CLC 




A 


□ □BEC 


ADC 


$Bt,a 


A 


□ □B5F 


ORA 


#$3D 


A 


DDB31 


JSR 


$FFDE 


A 


□ 0B3^ 


LDA 


#$PD 


A 


□ 0B3t 


JSR 


$FFDE 


A 


□ 0B3q 


RTS 





As a matter of style, you might prefer to type addresses as four digits of 
hex ($DBDD rather than SBDD) to remind yourself that you're dealing 
with sixteen bits. The dollar sign isn't needed, but I suggest you keep it. 
When you graduate to a full symbolic assembler, you'll be required to use 
the dollar sign; you might as well keep in practice. 



The assembled screen code looks like this: 



A 


□ □Bit 


EO 


DD 


□ B 


JSR 


$DB^^ 


A 


ODBiq 


flD 




□ B 


STA 


$QBba 


A 


□ □BIG 


Aq 


EB 




LDA 


#$EB 


A 


□ □BIE 


£□ 


DE 


FF 


JSR 


$FFDE 


A 


□ □BEl 


BQ 


□ □ 


□ B 


JSR 


$DB^^ 


A 




AA 






TAX 




A 


□ □BS5 


AS 


3D 




LDA 


#$3D 


A 


□ □BE? 


ED 


DE 


FF 


JSR 


$FFDE 


A 


□ □BEA 


flA 






TXA 




A 


□ □BEB 


Ifl 






CLC 




A 


□ □BEC 


LD 


hU 


□ B 


ADC 


$^Bt^ 


A 


□ □BEF 


□q 


3D 




ORA 


#$3^ 


A 


□ □B31 


ED 


DE 


FF 


JSR 


$FFDE 


A 


UUBIA 


Aq 


□ D 




LDA 


#$□0 


A 


□ □B3b 


ED 


DE 


FF 


JSR 


$FFDE 


A 


□ □B3q 


tD 






RTS 





Remember we don't want to SYS to address $BD^ (S flit)— that's the 
subroutine. Instead, command BANK 15:SYS 2838 which takes us to the 
main routine at $ □Bit. 



APPENDIX E — EXERCISES FOR THE C128 



265 



From Chapter 5: 

Project: Screen Manipulation 

It's not possible to do a simple POKE to the screen when you are in the 
Commodore 1 28's 80-column mode, so this example must be for the 40- 
column configuration only. The first instruction uses a decimal value of 40 
rather than hex 28. 



ft DDBOO 


LDft 


* + A0 


ft DDBOe 


STft 


$B&D 


The 40-column screen is usually at $04 DO. 


ft DDBDS 


LDX 


*$UA 


ft DDBD? 


STX 


$BC 


ft DDBaq 


LDft 


#$□□ 


A DDBOB 


STft 


$BB 


ft DDBOD 


LDX 


#□ 


Here's where we start on a new line 


ft ODBDF 


LDY 


#$UA 


And this is where we handle the next column. 


A □□Bll 


LDA 


($BB) ,Y 


ft DOBIB 


CMP 


#$E0 


ft ODBIB 


BEQ 


$B1S 


ft DDBl? 


EOR 


#$flD 


ft DOBiq 


STft 


($BB) ,Y 


A ODBIB 


INY 




A DDBIC 


CPY 


# + lfl 


ft ODBIE 


BCC 


$B11 


ft ODBEO 


CLC 




ft DDBEl 


LDft 


$BB 


ft DOBEB 


ftDC 


$B&0 


A DDBEb 


STft 


$BB 


A DDBEfi 


LDft 


$BC 


A DDBEA 


ftDC 


#$□□ 


ft DOBEC 


STft 


$BC 


ft ODBEE 


INX 




ft DOBEF 


CPX 


# + lA 


ft DOBai 


BNE 


$BDF 


A DOBBB 


RTS 




The assembled code 


will look like the following. There's not enough room 



on the screen to see it all at once, 

ft DDBDa ftq Efi LDft #$Efl 

ft DQBDE flD flD DB STft SDBflD 

ft □□B05 ftE 04 LDX #$04 



266 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



H 


U U D U f 


AL 

U D 


RP 
DC 


O X A 


i;rp 


B 

n 


U U D U n 




nn 

U u 




7r ^ u u 


a 


U U O UD 




RR 
DD 


O X n 


■CRR 

4>DD 


a 

n 


nnRnn 

U U D u u 


a p 


nn 

U U 


T n Y 

J-i JJ A 


a6t<t;nn 

#^iP u u 


n 
n 


nnRiTP 
u UD u r 


a n 




T nv 




a 

n 


nriRi.i. 


R1. 
D Jj 


RR 
DD 


i-i JJ n 


^ "RRR ^ V 
\ 4>DD ^ / 1 


B 
xi 


U UD Jj J 


PP 


C U 


PMP 


W9CU 


n 

n 


U Imi *J M J 


X LJ 


□ 3 

LJ L_ 


BEO 


4* LJ U JU 1 


ft 


□ OBI? 

LJ LJ XJ JJ 1 




fin 

U LJ 


EOR 


TT LJ LJ 


a 






BB 


STA 

ij X n 


( $BB ^ . Y 


a 


□ □BIB 

LJ U U ^ JJ 


LJ 




INY 

X Li X 




a 


U LJ U JJ ^ 


CO 

LJ 




CPY 


#$1P 

TT JJ I— 


ft 


□ □BIE 

LJ LJ U JJ U 


1 LJ 


X JJ 


BCC 

u v_« v« 


*|f U U ^ Jl 


a 


□ □B3^ 

U LJ U ^ LJ 


JJ LJ 




CLC 

v« xj %^ 






LJ LJ JJ JU 


n? 

n J 


BB 

JJ JJ 


i./ fl 


$BB 

4J AJ XJ 


a 

n 


LJ LJ U L. ^ 


□ ly 


LJ LJ 


□ B ADC 

LJ JJ XI jy ^ 


SDBfin 

*if LJ JU LJ LJ 


n 

n 


U U D C D 


U 3 


iJ xj 


tj X A 




A 


ooBaa 


AS 


BC 


LDA 


$BC 


A 


□ □B5A 




□ □ 


ADC 


#$□□ 


A 


□□sac 


fiE 


BC 


STA 


$BC 


A 


□ DB5E 


Efl 




INX 




A 


□ □B2F 


ED 


□E 


CPX 


#$DE 


A 


□ □B31 


DD 


DC 


BNE 


$DBDF 


A 


□ □B33 


to 




RTS 





Now for the BASIC program to demonstrate how it all works: 
IQQ BANK 15 
IID FOE J = l to ID 
lEO SYS Efilt 
130 FOR K = l to 5DD 
KO NEXT K/ J 



From Chapter 6: 

We can do the exercise, but there are new rules that we must iearn. 

The Commodore 128 has more than one bank of memory, and different 
things are found In different banks. The role of pointers in keeping various 
types of data separate is not the same as before. An earlier Commodore 
machine (the B-128 or 700 series) had this same kind of muiti-bank ar- 
chitecture, and some of the following comments will also apply to that 
machine. 



APPENDIX E — EXERCISES FOR THE C128 



267 



Siting Beliind BASIC 

About the pointers: Our BASIC program is in bank 0, but the variables, 
arrays and strings are in bank 1 . This means that the start-of-BASIC pointer 
works with a different memory bank than the others. When we place a 
machine language program directly behind a BASIC program we are in 
no danger of bumping into variables. There is a pointer, saying where the 
empty space starts in bank — the pointer is at hex 1 E 1 □ , decimal AhEA — 
but it mustn't be confused with start-of-varlables. 

On the Commodore 128, a BASIC program usually is stored at address 
$1CD1. The address may change if graphics functions are used. That's 
quite a high address compared to most other Commodore machines. You 
may establish where a program ends by checking addresses $ 1 E 1 □ and 
$1E11. If you wish to write a program that will be located in bank but 
above your BASIC program, the pointer will tell you the area that's safe. 
After you have placed your program in the appropriate part of memory, 
you may move the pointer up. From that point on, BASIC and machine 
language will load and save together as a unit. 

We're going to use this parked-behind-BASIC location in the exercise. 
There's one more caution, however. If you want the ease of bank 15 
operation, with simple access to your program In RAM and the Kernal In 
ROM, you must make sure that your programs — BASIC and machine 
language together — don't go above address $ADQQ. Beyond that point, 
you'll have to carefully call banking subroutines — principally the one at 
$ □ E CD— to make sure that everything works together. For our tiny sample 
program, that's no problem. 



Crossing The Banics 

Here's a new problem. Our program— located in bank 0— is going to look 
at and change BASIC variables as they lie in memory. How can a program 
in bank look at and change data in bank 1 ? We must learn about the 
subroutines that allow us to do this. 

To LOAD from any memory bank, we must call subroutine INDFET (indirect 
fetch), located at address $TT7A. Set things up as if you are about to 
do a LDA (..),Y command. That calls for first setting up an indirect address 
somewhere in page zero. Tell the subroutine where the indirect address 
is located by loading its address into the A register. Then load the bank 
number into register X, load Y with an appropriate value for indirect use, 
and call JSR $FF7<.The data from the appropriate bank will be re- 
turned in the A register. 



268 MACHINE LANGUAGE FOR COMMODORE MACHINES 



To STORE in any memory bank, we must call subroutine INDSTA (indirect 
stash), located at address $FF77. Set things up as if you are about to 
do a STA (..),Y command. That calls for first setting up an indirect address 
somewhere in page zero. Tell the subroutine where the indirect address 
is located by storing it into address SDEBR. Then load the bank number 
into register X, load A with the data to be stored, load Y with an appropriate 
value for indirect use, and call JSR $FF77. The data will be stored in 
the appropriate bank. 

Project 

Type NEW and enter the BASIC program as follows: 
IDD V^ = D:BaNK 15 
110 FOR J = l TO 5 
lED INPUT "VaLUE" ; 
13D SYS + + + + 
lAO PRINT "TIMES TEN = ";V% 
15D NEXT J 

Assuming that our BASIC program will occupy less than 127 bytes and 
that BASIC starts at IICDI (decimal 7169) we can start our machine 
language program at around 7169 + 127, or 7296 (hexadecimal ICflD). 
On that basis, we may change line 13D to SYS 7EREj. Do nof try to 
run the program yet. It would be a good idea to call the monitor briefly 
and display the contents of memory address 151D-1E11 to confirm 
that we are in the right range. 

Switch into the machine language monitor. Assemble the following code, 



(the indirect address) 
(bank 1) 



but don't type 


the comments 


A 


DlCflD 


LDY 


#$DE 


A 


DlCflE 


SEI 




A 


DlCflB 


LDA 


#$5F 


A 


□ ICflS 


LDX 


#$□1 


A 


□ lCfl7 


JSR 


$FF7A 


A 


OlCflA 


STA 


$DBDO 


A 


OlCflD 


STA 


$□302 


A 


□icqo 


LDY 


#$□3 


A 


□icq? 


LDA 


#$2F 


A 


□ ICS-^ 


LDX 


#$□1 


A 


□icqt 


JSR 


$FF7< 


A 


□icqq 


CLI 




A 


DicqA 


STA 


SQEQl 


A 


DicqD 


STA 


$aBa3 


A 


□ ICAD 


ASL 


SDBDl 


A 


01CA3 


ROL 


SOBOa 



APPENDIX E — EXERCISES FOR THE C128 



269 



A 
k 
h 
h 
A 
A 
A 
A 
A 
A 
A 
A 
A 
A 
A 
A 
A 
A 
A 
A 
A 
A 
A 



□ ICAb 
OICAR 
OICAC 
QICAD 

□ ICBD 

□ 1CB3 

□ ICBt 

□ ICBR 

□ ICBC 

□ ICBF 

□icca 

01CC5 
OlCCb 
DlCCfl 
DICCA 

□ ICCD 

□ ICCF 
01CD2 

□ 1CD5 

□ 1CD7 

□ ICDA 

□ ICDC 

□ ICDF 
DICED 



ASL 
ROL 
CLC 
LDA 
ADC 
STA 
LDA 
ADC 
STA 
ASL 
ROL 
SEI 
LDY 
LDA 
STA 
LDX 
LDA 
JSR 
LDY 
LDA 
LDX 
JSR 
CLI 
RTS 



$DBD1 
$DBDD 

$DBai 
$DBD3 
SDBQl 
$DBDD 
SDBDE 
$DBDD 
$DB01 
$DBDD 

#$Q5 

#$EF 

$DEBR 

#$□1 

$OBDD 

$FF77 

#$□3 

$DB01 

#$01 

$FF77 



(the indirect address) 
(bank 1) 



The assembled code will look like this: 



A 


DlCfiD 


AD 


DE 




LDY 


#$DE 


A 


□ ICfiS 


7fl 






SEI 




A 


Dica3 


Aq 


EF 




LDA 


#$EF 


A 


□ ICflB 


A5 


Dl 




LDX 


#$D1 


A 


□ lCfl7 


ED 


7A 


FF 


JSR 


$T?7A 


A 


□ ICflA 


flD 


OD 


DB 


STA 


$DBDD 


A 


□ ICflD 


BD 


DE 


DB 


STA 


$DBDE 


A 


DIC^D 


AD 


D3 




LDY 


#$03 


A 


□icqs 


AH 


EF 




LDA 


#$EF 


A 


□icq< 


Ad 


Dl 




LDX 


#$01 


A 


DlCRt 


2D 


7A 


FF 


JSR 


$FF7/; 


A 


Dicqq 


5fl 






CLI 




A 


DicqA 


flD 


Dl 


DB 


STA 


$0B01 


A 


DICHD 


fiD 


D3 


DB 


STA 


$0B03 


A 


□ ICAD 


DE 


Dl 


DB 


ASL 


$0601 


A 


D1CA3 


EE 


DD 


DB 


ROL 


$0B00 


A 


DlCAt 


DE 


Dl 


DB 


ASL 


$0B01 


A 


DICAR 


EE 


DD 


DB 


ROL 


$DBOD 



270 MACHINE LANGUAGE FOR COMMODORE MACHINES 



A 


OICAC 


Ifl 






CLC 




A 


□ ICAD 


AD 


Dl 


DB 


LDA 


$DBDl 


A 


□ ICBD 


tD 


D3 


DB 


ADC 


$nBD3 


A 


□ 1CB3 


flD 


Dl 


DB 


STA 


$DBD1 


A 


□ ICBt 


AD 


DD 


DB 


LDA 


$DBDD 


A 


□ 1CB9 


bD 


□ E 


DB 


ADC 


$DBDE 


A 


□ ICBC 


flD 


DD 


DB 


STA 


$PBDD 


A 


OICBF 


□E 


Dl 


DB 


ASL 


$DBD1 


A 


01CC2 


5E 


DD 


DB 


ROL 


$DBDD 


A 


□ 1CC5 


7a 






SEI 




A 


□ ICCt 


AD 


DE 




LDY 


#$DE 


A 


Dicca 


A=1 


SF 




LDA 


#$SF 


A 


□ ICGA 


fiD 


B'=\ 


DE 


STA 


$DEB'^ 


A 


□ ICCD 


AS 


Dl 




LDX 


#$D1 




OICCF 


AD 


DD 


DB 


LDA 


SDBOD 

1— 1 iJ LJ LJ 


A 


01CD2 


ED 


77 


FF 


JSR 


$FF77 


A 


□ 1CD5 


AD 


D3 




LDY 


#$D3 


A 


□ 1CD7 


AD 


Dl 


DB 


LDA 


$0BD1 


A 


□ ICDA 


A5 


Dl 




LDX 


#$D1 


A 


OICDC 


2D 


77 


FF 


JSR 


$FF77 


A 


□ ICDF 


5fl 






CLI 




A 


DICED 


to 






RTS 





We must change the End-of-BASIC pointer to a location above the ma- 
chine language program. That would be $1CE1, and so we display the 
BOB pointer with M lElD 1 Ell and change the pointer to 
>1S1D El IC ............ 

Check . . . disassemble . . . and then back to BASIC. List, and you'll see 
your BASIC program again. There's no sign of the machine language 
program, of course, but SAVE will now save everything together. You may 
now RUN. 

From Chapter 7: 

Interrupt Exercise 

The interrupt: 

A DDBDD LDA 

A DDBDE STA 

A DDBD5 JMP 
The enable: 

A DDBDfl LDA 

A DDBDB STA 

A DDBDE LDA 

A DDBll STA 



$qi 

$D4DD 
($DB5D) 

$D31A 
$DB5D 
$D315 
$DB51 



APPENDIX E — EXERCISES FOR THE C128 



271 



A 


□ □BI^ 


SEI 








A 


□ 0B15 


LDfl 


, #$□□ 






k 


□ DB17 


STA 


, $^31^ 




A 


DDBliA 


LDA 


, #$^B 






A 


DDBIC 


STA 


, $D31^ 




A 


□ QBIF 


CLI 








A 


DDB5D 


RTS 










The disable: 












A 


ODBai 


SEI 










A 


□ □B5a 


LDA 


$UBSO 




A 


□ □B25 


STA 


$□314 




A 


DDBSa 


LDA 


$DB51 




A 


□ 0B2B 


STA 


$0315 




A 


OOBEE 


CLI 










A 


□ □B2F 


RTS 










The completed program should look like this: 


A 


□ □BDD 


AS 






LDA 


$S1 


A 


Q0BD2 


flD 


□ □ 


DA 


STA 


$0400 


A 


□ □BQ5 


tc 


SD 


QB 


JMP 


($DB5D) 


A 


□ □BDfl 


AD 




03 


LDA 


$0314 


A 


□ QBOB 


flD 


50 


□ B 


STA 


$0B5D 


A 


ODBDE 


AD 


15 


□ 3 


LDA 


$□315 


A 


□ □Bll 


flD 


51 


□ B 


STA 


$0B51 


A 


□ QB14 


7fl 






SEI 




A 


0QB15 


AS 


□ □ 




LDA 


#$00 


A 


DDB17 


flD 




03 


STA 


$0314 


A 


ODBIA 


Aq 


OB 




LDA 


#$DB 


A 


□ OBIC 


flD 


15 


□ 3 


STA 


$□315 


A 


ODBIF 


5fl 






CLI 




A 


□ □BSD 


i=n 






RTS 




A 


□ □BEl 


7fl 






SEI 




A 


□ aB22 


AD 


50 


□ B 


LDA 


$0B5^ 


A 


□ □B25 


flD 


lA 


□ 3 


STA 


$□314 


A 


□ □BEfl 


AD 


51 


□ B 


LDA 


$DB51 


A 


□ □BEB 


flD 


15 


□ 3 


STA 


$□315 


A 


□ □BEE 


5fl 






CLI 




A 


□ □BEF 








RTS 





Enable the new interrupt procedure by a SYS to $^B^fl, above (SYS 
2824). Return to the "standard" interrupt with a call to $^BS1 (SYS 2849). 

Project: Adding a Command 

CHRGET is now at address $03 flD. TXTPTR is still in zero page, how- 
ever, at $ 3D. We use coding quite similar to that for the Commodore 64. 



272 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Here's the "intercept": 





□ OBDO 

L-l LJ LJ LJ LJ 


LDY 


#1 


ft 


OOBDE 


LDA 


( S3D ) . Y 


A 


□ □BD^ 


CMP 


#SEt 




LJ LJ ±J LJ O 


U J-J \^ 


SBDB 

JL/ LJ U 


ft 


I—I LJ U LJ LJ 


JMP 


V LJ XJ — J LJ J 


ft 


□ □BOB 

LJ LJ U LJ U 


JSR 

KJ t>J L\ 


$0360 

k|/ LJ J LJ IJ 


A 

CI 


U LJ LJ LJ JJJ 


LDY 


#0 

TT LJ 


ft 


□ □BID 

LJ LJ LJ LJ 


LDA 


TT 4* ^ n 


A 


□DBia 


JSR 


$FFDE 


a 


noBis 


INY 




A 


□ □Bib 


CPY 


# + !□ 


A 


OOBlfl 


BCC 


$B1E 


A 


□ OBIA 


LDA 


#$0D 


A 


□ OBIC 


JSR 


$FFDE 


A 


ODBIF 


JMP 


$BDfi 


ere's the link to turn it on: 


A 




LDA 


$D30fl 


A 


□ □B55 


STA 


$B5D 


A 


□ □BEfl 


LDA 


$D3Qq 


A 


□ □BEE 


STA 


$B51 


A 


DOBEE 


LDA 


#$DD 


A 


00B3D 


STA 


$03Dfl 


A 


□ □B33 


LDA 


#$DB 


A 


0DB35 


STA 


$D30q 


A 


□ □B3fl 


RTS 





The assembled code will look like this: 



a 


□ □BQD 


AO 


01 




LDY 


#$□1 


A 


□ OBOE 


Bl 


3D 




LDA 


{$3D) ,Y 


A 


□ □BD4 


cq 


Et 




CMP 


#$Efc 


A 


□ □BDt 


FD 


□ 3 




BEQ 


$^B^B 


A 


□ □BOfi 


tc 


5^ 


□ B 


JMP 


($^B5^) 


A 


□ □BOB 


E^ 




□ 3 


JSR 


$^3aD 


A 


QDBDE 


A^ 


□ □ 




LDY 


#$□□ 


A 


□ OBIO 


Aq 


EA 




LDA 


#$EA 


A 


□ □BIE 


E^ 


DE 


FF 


JSR 


$FFDE 


A 


□ □B15 


Cfl 






INY 




A 


□ □Bit 


€□ 


□ A 




CPY 


#$^A 


A 


□ □Blfi 


q^ 


Ffl 




BCC 


$^B1E 


A 


□ □BIA 


aq 


□ D 




LDA 


#$DD 


A 


□ □BIC 


£□ 


DE 


FF 


JSR 


$FFDE 


A 


□ □BIF 


<c 


□a 


□ B 


JMP 


$^B^a 


A 


□ □BEE 


AD 


□a 


□ 3 


LDA 


$^3Qa 



APPENDIX E — EXERCISES FOR THE C128 



273 



a DDBES 
ft ODBEfl 
A DDBEB 
A DDBEE 
ft ODBaO 
A DDBBB 
A DDBBB 
A DDBBfl 



flD 50 

AD oq 

flD 51 
AR □□ 
flD Dfl 
AS OB 
flD 

to 



□ B STA 

□ 3 LDA 

□ B STA 

LDA 
03 STA 

LDA 
03 STA 

RTS 



SOBSO 

$03Dq 

$0B51 

#$00 

$030a 

#$DB 

$030^ 



When you have completed and checked the code return to BASIC. Type 
NEW and write the following program: 

100 PRINT 3+^:&:PRINT 5+t 

110 & 

150 PRINT "THAT'S ALL" 
Type RUN and you'll get a SYNTAX ERROR in line 100. Now implement 
the "ampersand" feature with BANK 15:SYS 2850. Type RUN again. The 
ampersand command obediently prints ten asterisks each time it is in- 
voked. A point of interest: in the two examples in this chapter, bank will 
work. Can you see why? 



From Chapter 8: 



Output Example 

To put the message HI on the printer: 

100 OPEN I, A 

110 BANK 15:SYS Efllfc 

lED CLOSE 1 
The machine language: 

A OOBOD LDX #$01 

A D0B02 JSR $FFCS 

A DDB05 LDA #$A& 

A 00BD7 JSR $FFDE 

A OOBOA LDA #$<q 

A OOBOC JSR $FFDE 

A DOBOF LDA #$0D 

A OOBll JSR $FFDE 

A 00B14 JSR $FFCC 

A 00B17 RTS 
The assembled code: 

A OOBOD AE 01 LDX #$01 

A OOBOE ED CH FF JSR $FFCH 

A DDBD5 AS A6 LDA #$4fl 

A DDB07 ED DE FF JSR $FFDE 



274 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



A □DBDA ftR LDft #$A^ 

a DDBDC EQ D5 FF JSR $FFDE 

a odBDF aq dd LDa #$dd 

a □□Bll 5D D2 FF JSR $FFD2 
a ODBK EO CC FF JSR $FFCC 
a DDBl? to RTS 
Input Example 

Create the file as described in Cliapter 8. The BASIC program is also 
similar except for the SYS command: 

!□□ OPEN 1, a, 3, "DEMO" 

IID BANK 15:SYS afllt 

12D CLOSE 1 
The machine language program: 

a DDBDn LDX #$□! 

a DDBDE JSR $FFCt 

a DDBDS JSR $FFE4 

a □DBDfl JSR $FFD5 

a noBDB LDa $qD 

a DDBGD BEQ $DBQ5 
a DDBaF JSR $FFCC 
a DOBIE RTS 
The assembled code: 



a 


□ □BDD 


RE 


Dl 




LDX 


#$D1 


a 


□ □BDE 


ED 


Cb 


FF 


JSR 


$FFCt 


a 


□ □BD5 


ED 


E4 


FF 


JSR 


$FFE^ 


a 


□ DBOfl 


ED 


DE 


FF 


JSR 


$FFD5 


a 


□ □BOB 


as 


qD 




LDa 


$qD 


a 


□ □BOD 


FD 


Ffc 




BEQ 


$DBD5 


a 


□ □BDF 


ED 


CC 


FF 


JSR 


$FFCC 


a 


□ □B12 


hU 






RTS 





A File Transfer Program 



Here comes BASIC: 

!□□ PRINT "FILE TRANSFER" 

!!□ INPUT "INPUT FROM (DISK, TAPE)" ; A$ 

lED IF LEFT$(A$,1) = "T" THEN OPEN 1:G0T0 ItD 

13D IF LEFT$(A$,1)<> "D" GOTO IID 

l^D INPUT "DISK FILE NAME" ;N$ 

15D OPEN l,fl,3,N$ 

ItD INPUT "TO (DISK, TAPE, SCREEN) ";B$ 

17D IF LEFT$(B$,1) = "S" THEN OPEN S,3:G0T0 E^D 

IflD IF LEFT$(B$,1) = "D" GOTO EID 

iqD IF LEFT$(B$,1)<>"T" GOTO ItD 



APPENDIX E — EXERCISES FOR THE C128 



275 



EDO IF LEFT$(A$,1) = "T" GOTO ItD 
EIQ INPUT "OUTPUT FILE NAME" ; F$ 
55D IF LEFT$(B$,1) = "D" THEN OPEN 

530 IF LEFTS (B$, 1) = "T" THEN OPEN E,l,lrF$ 

2An BANK 15:SYS 7tflD 

ESn CLOSE E: CLOSE 1 
The above BASIC program should not take up more than 51 1 bytes; on 
a standard Commodore 128, that means that we'll have clear space for 
our machine language program starting at $1ED0 (decimal 7680). We'll 
move the end-of-BASIC pointer along, of course (NOT the start-of-vari- 
ables), so that our machine language program will save together with 
BASIC. 



A 


□ lEDD 


LDX 


#$D1 






A 


□ lEDE 


JSR 


$FFCt 




A 


□ lEDS 


JSR 


$FFE< 






A 


□ lEDfl 


LDX 


$10 






A 


□ lEOA 


PHP 










A 


□ lEDB 


PHA 










A 


□ lEOC 


JSR 


$FFCC 




A 


QIEQF 


LDX 


#$DE 






A 


□ lEll 


JSR 


$FFCq 






A 


□ 1E14 


PLA 










A 


01E15 


JSR 


$FFDE 






A 


OlElfl 


JSR 


$FFCC 




A 


OIEIB 


PLP 










A 


□ lElC 


BEQ 


$1E00 






A 


□ lElE 


RTS 










le assembled code is: 








A 


□ lEDD 


AE 


Dl 




LDX 


#$D1 


A 


□ lEDE 


ED 


Ct 


FF 


JSR 


$FFCt 


A 


□ 1ED5 


ED 


EA 


FF 


JSR 


$FFE4 


A 


OlEDfl 


At 


^Q 




LDX 


$SD 


A 


□ lEDA 


Dfl 






PHP 




A 


□ lEDB 


^fl 






PHA 




A 


□ lEOC 


ED 


CC 


FF 


JSR 


$FFCC 


A 


DIEOF 


AE 


DE 




LDX 


#$DE 


A 


DlEll 


EO 


cq 


FF 


JSR 


$FFCq 


A 


OIEIA 


tfl 






PLA 




A 


□ 1E15 


ED 


DE 


FF 


JSR 


$FFDE 


A 


□lEia 


ED 


CC 


FF 


JSR 


$FFCC 


A 


□ lElB 


Efl 






PLP 




A 


OIEIC 


FD 


EE 




BEQ 


$1EDD 



276 MACHINE LANGUAGE FOR COMMODORE MACHINES 



A DIEIE to BTS 
Be sure to move the Start-of-Variables pointer ($D2ia/$DEll) so that 
it points at address $1E1F. 



F 

Floating 
Point 
Representation 



277 



278 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Packed: 5 bytes (as found in variable or array) 



Zero 
Flag/ 
Exponent 



Mantissa (value) 
4 bytes 



High bit represents sign of mantissa 
Unpacl<ed: 6 bytes (as found in floating accumulator) 



ZF/ 
Exponent 



1 










Mantissa- 


—4 Bytes 



Sign 
(High Or- 
der 
Bit only) 



• If exponent = 0, the whole number is zero 

• if exponent > $80, the decimal point is to be set as many places to the 
right as the exponent exceeds $80. 

• Example: Exponent: $83 mantissa: 11000000 . . . binary set the point 
three positions over: 1 10.000 ... to give a value of 6. 

• If exponent < = $80, the number is a fraction less than 1 . 

Exercise: Represent +27 in Floating Point 

27 decimal = 1 101 1 binary; mantissa = 1 101 1000 ... the point is to be 
positioned 5 places in (1 101 1 .000 . . .) so we get: 
Exponent: $85 mantissa: 11011 000 . . . binary or D8 QO 00 00 hexadecimal 
To pack, we replace the first bit of the mantissa with a sign bit (0 for 
positive) and arrive at: 

fl5 5fl □□ OD □□ 



G 



Uncrashing 



It's best to write a program that doesn't fail (or "crash"). Not all of us 
succeed in doing this. 

If a program gives trouble, it should be tested using breakpoint techniques. 
The BRK (break) instruction is inserted at several strategic points within 
the program. The program stops (or "breaks") at these points, and the 
programmer has an opportunity to confirm correct behavior of the program 
at selected points. Using this technique, a fault can be pinned down quite 
closely. 

Occasionally, usually because of bad planning, a program crashes and 
the cause of the crash cannot be identified. Worse still, a lengthy program 
crashes and the user has forgotten to save a copy of it; the user is then 
faced with the task of putting it in all over again. 

In such cases, uncrashing techniques are sometimes available to bring 
the computer back from limbo. They are never entirely satisfactory, and 
should be thought of as a last resort. 

The technique differs from computer to computer. 



279 



280 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



PET/CBM 

Original ROM PETs cannot be uncrashed. 

Subsequent models can be uncrashed, though hardware additions are 
necessary. The reader should find someone with computer hardware 
knowledge to assist in fitting the switches to the computer. 

A toggle switch is needed, to be connected to the "diagnostic sense" line 
of the parallel user port; that's pin 5 of the PUP. The other side of the 
toggle switch should connect to ground (pin IE). 

Additionally, a momentary pushbutton is required. This must connect the 
reset line of the computer to ground. Technically speaking, it's better to 
trigger the input of the computer's power-on reset chip (a 5 55 one-shot), 
using a resistor to guard against accidentally grounding a live circuit. 

To uncrash, set the toggle switch to "on" and press the pushbutton; the 
machine will come back to life in the machine language monitor. Set the 
toggle switch off. There's more work to do. 

The computer is still in an unstable state. To correct this, either of two 
actions may be taken. You may return to BASIC with . X and immediately 
give the command CLE; Alternatively, you may type . ; followed by the 
RETURN key. 

Whatever investigation or other action is needed should be performed 
quickly and the computer reset to its normal state. 



VIC/Commodore 64 

You might try holding down the RUN/STOP key and tapping the 
RESTORE key to see if that will bring the machine to its senses. 0th- 
enwise, you must do a more serious reset. 

You must depend on the fact that the computer does a nondestructive 
memory test during reset. There are various commercially available in- 
terfaces for the cartridge port— usually "mother boards" that are fitted with 
reset switches. 

When the reset switch is pressed, the computer starts from the beginning; 
but memory is not disturbed. If you have logged the entry location of the 
machine language monitor, you can bring it back with the appropriate SYS 
command. 



APPENDIX G — COMMODORE PLUS/4 



281 



Commodore PLUS/4 

There's a reset button next to the power switch. Before you press it, hold 
down the RUN/STOP and CTRL l^eys. Now press the reset button and 
you'll find yourself in the machine language monitor. 



H 

Supermon 
Instructions 

Commodore 128 users should turn to page 290, which also Includes a 
summary of instructions to SUPERMON+ for C64 users who also want a 
better monitor. 

Program Supermon is not a monitor; it is a monitor generator that will 
make a machine language monitor for you. There's a reason for this. 
Supermon finds a likely spot in memory and then plunks the MLM there 
so as to fit it into the most suitable place. 

Load Supermon and say RUN. It will write an MLM for you, and call it up. 
Now, exit back to BASIC and command NEW. You do not want the MLM 
builder any more (it's done the job) and you do not want the danger of 
building two — or more — MLM's. Get rid of the generator program. Any 
time you need to use the MLM, give SYS^ or SYSfl, as appropriate. 

Supermon contains the following "essential" commands: 

R — to display (and change) registers 
M — to display (and change) memory 
S — to save memory to disk or tape 
L — to load from disk or tape 
G — to go to an ML program 
X— to exit to BASIC 

Supermon also contains the following extra commands: 

A — to assemble 
D — to disassemble 



283 



284 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Most versions of Supermon (not the "do-it-yourself" below) contain the 
following commands. Though not used by this book, they are useful: 

F — fills memory with fixed contents: 

F l&nO IflFF □□ 
H — hunts for a memory pattern: 

H DfiDD IfiDD 2D D2 FF 
T — transfers a block of memory to a new location: 

T DfiDO DBFF flDDD 

A few versions of Supermon contain the command .1 which causes ma- 
chine language single stepping. 

A Do-lt-Yourself Supermon 

If you do not have access to Supermon from friends, dealers, clubs, or 
disk, you may find the following program useful for the Commodore 64 
only. 

Enter this program (it will take you hours). Be sure that lines 3QD and 
above are correct; the lower numbered DATA lines will be checked for 
accuracy by the program. 

When you say EON, the program will run in two phases. Part 1 takes over 
two minutes to run: it will check all DATA statements for missing lines 
and errors and report any problems to you. Part 2 will run only if part 1 
shows no errors: it will cause the program to "collapse" into itself, resulting 
in Supermon. The moment the program has completed running, save 
Supermon to disk or tape. 

The Supermon generated by this program is a "junior" version (to save 
your fingers) but it contains all commands needed for this book. 

1 DATA Bb, fl, 153, 34, 1^7, ia,Eq,Eq, - 3D 

2 DATA 2q,Bq,fl3,fi5,flD,tq,aE,32,54,5E,-lt 

3 DATA 45,77,?q,7fi,D,4q,fl,llD,D,153,-3q 
A DATA 34,17,32,3E,3E,3E,3E,3E,3E,3E,-5D 
5 DATA 3E,3E,3E,3E,3E,3E,3E,D,75,fl, -3 

t DATA lED,n,153,34,17,3E,4fc,4fc,74,73,-4fl 

7 DATA 77,3E,bb,fl5,fl<,fl4,bq,fiE,7D,73,-5b 

fl DATA tq,7fc,tfi,D,lDE,fl,13D,D,15fl,4D, -4 

q DATA iq4,<D,5E,51,41,17D,5D,53,54,17E, -53 

ID DATA iq<,<D,5E,5E,41,17D,4q,5D,55,41, -E5 

11 DATA D,D,D,17D,17D,17D,17D,17D,17D,17D, -fc^ 

IE DATA 17D,17D,170,17D,17D,17D,17D,17D,17D,17D, -Eq 



APPENDIX H — A DO-IT-YOURSELF SUPERMON 



285 



13 DaTR 17D, 170, 17D, 170,170, 170, 17D, Its, <5, 133, -bl 

lA DATR 3^, lb5,4t, 133, 35, Its, 55, 133, 3b, Its, - IE 

15 DRTA 5b,133,37,lbD,D,lt,5,3<,2Dfl,5,lRa, -55 

lb DRTa 3 5,iqa,3^,177,3<,B0fl,b0,lb5,34,EDfl, -34 

17 DATA E,iqa, 35, 1^3,3-^,177, 34,24 0,33,133, -52 

Ifl DfiTR 3fl,lb5,34,EDfl,5,iqfl,3 5,iqfl,34,17 7, -bD 

iq DATA 34,E4,lQl,3b,17D,lb5,3 6,iai,37 ,7 2, -5b 

ED DftTft lb5, 55, EOfl,E,iqfl, 5b, IRfl, 55,104, 145,-1 

El DRTft 55,13a,7E,lb5,55,EDfi,E,lSa,5b,iqa, -1 

EE DftTft 55, 104,145, 55, E4, 144, iaE,E01,7q,EDa, - 4a 

E3 DftTft E37,lb5,55,133,51,lb5,5b,133,5E,lDa, -17 

E4 DftTft 55, □,7q, 7 q,7q,7q, 173, E3D,E55,D, - EE 

E5 DftTft 14 1, EE, 3, 173, E31,E55, 0,141,23, 3, -b4 

Eb DftTft lbq,lEa,3E,144,E55,D,D,Elb,lD4,141,-3D 

E7 DftTft bE,E,104,l41,bl,E,104,141,bO,E, -41 

Ea DftTft 104, 141, Sq, 2, 104, 17 0, 104, Iba, 5b, 13a, -17 

Eq DftTft E33,E,141,5a,E,152,E33,0,0,141, - IE 

30 DftTft 57,E,iab,14E,b3,2,32,147,E53,0, -57 

31 DftTft lbE,bb,lbq,4E,3E,ED5,251,0,lbq,aE, -bE 
3E DftTft E0a,4E,E3D,iq3,E0a,b,E30,iq4,E0a,2, -52 

33 DftTft E3D,3a,qb,3E,ED7,S55,E01,13,2Dfl,24a, -24 

34 DftTft 104,104,lbq,0,D,133,3a,lb2,13,lbq, -11 

35 DftTft 4 b, 32, 205, 251, 0,32, 220, 24q, 0,201, -32 

3b DftTft 4b,24 0,24q,201,32,24D,245,lb2,14,221, -23 

37 DftTft iq5,255,D,20a,12,13a,10,17 0,iaq,207, -3b 

3a DftTft 255,0,72,iaq,20b,255,0,7 2,qb,2D2, -E 

3q DATA lb,E3b,7b,a0,E5E,D,lb5,iq3,141,5a, - Eq 

40 DATA E,lb5,iq4,141,57,E,qb,lbq,a,133, -44 

41 DATA Eq,lb0,0,0,3E,143,E53,0,177,iq3, -31 

42 DATA 32,iq0,251,0,32,2Dq,24q,D,iqa,2q, -bl 

43 DATA 20a,241,qb,32,254,251,0,144,ll,lb2, -53 

44 DATA 0,0,12q,iq3,iq3,iq3,24 0,3,7b,aD, -5a 

45 DftTft E5E,o,3E,Eoq,E4q,o,iqa,Eq,qb,ibq, -5b 
4b DftTft 5q,i33,iq3,ibq,2,i33,iq4,ibq,5,qb, -20 

47 DftTft 152, 7 E, 3E, 147, 253,0, 104, lb2, 4 b, 7 b, -44 

4a DftTft 205,251,0,lb2,0,0,iaq,E34,E55,D, -31 

4q DftTft 3E, ElO, S55, E3E,EE4, EE, E0a,E4 5, lb0,5q, -51 

50 DftTft 3E,ab,E50,0,173,57,E,3E,iq0,E51, -4 

51 DftTft 0,173,5a,E,3E,iq0,E51,0,3E,75, -31 
5E DftTft E50,0,3E,33,E50,0,E4D,a7,3E,220, -13 

53 DftTft 24q,0,32,23q,251,0,144,4b,32,223, - 40 

54 DftTft 251, 0,32, 220, 24q,0,3E,23q, 251,0, -51 

55 DftTft 144,35,32,223,251,0,32,225,255,24 0,-33 



286 MACHINE LANGUAGE FOR COMMODORE MACHINES 



5t DRTa LD,lbfc,3fl,5Dfl,5t,lfc5,lR5,iq7,iq3,lfc5, -2E 

5 a DATfi 0, 32, 163, E51, 0,32, 31, ESQ, 0,E4 

5R DATA EE4,7b,flD,E5E,0,3E,E3R,E51,D,l^^, - ^E 

bD DATA 3,3E,ED,E5D,0,3E,75,E5D,D,EDfl,-'^3 

bl DATA 7,3E,E3q,E51,D,l'^4,E35,lt,q,fl,133, -Efl 

fcE DATA Eq,3E,EED,E4R,D,3E,53,E5D,0,SDfi, -Ifl 

t3 DATA E^ a, 7 fc, ESq, E4 S,D,3E,ED7, ESS, EDI, 13, - EE 

l,A DATA E4D,lE,E01,3E,E0a,EDq,3E,E3q,E51,D, -57 

tS DATA 144,3,3E,En,E5D,D,17'^,b3,E,154, - ^b 

DATA lE0,17 3,57,E,7E,17 3,5a,E,7E,173, -35 

b7 DATA 5S,E,7E,173,fcD,E,174,fcl,E,17E, -55 

ba DATA tE,E,fc^,17'^,fc3,E,15<,ina,E,lbD, -5fc 

DATA lfcD,l,13E,iab,13E,ia5,13b,13E,ia3,13E, -E7 

7D DATA l<4,13E,1^7,lbq,fc'^ ,133,ia7,lbR,E,133, -iq 

71 DATA iaa,3E,ED7,E55,S01,3E,E^D,E^q,EDl,13,-^E 

7E DATA E^D,5b,EDl,3^,EDa,ED,3E,ED7,E5S,EDl, -35 

73 DATA 3<,E<D,lfc,EDl,13,E^D,^l,1^5,ia7,E3D,-3q 

7 A DATA ia3,EDD,iqE,lt,EDfl,E3b,7t,aD,E5E,D,-lfl 

7 5 DATA 3E, E07, ESS, EDI, 13, E^ □, EE, EDI, 44, SOa, -51 

7b DATA EED,3E,E5^,E51,D,<1,15,E4D,E33,ED1, -^t 

77 DATA 3, E4 □, EER, 133, lab, 3 E,ED7, ESS, EDI, 13, -<5 

7a DATA qt, IDa,^ a, 3, lDa,5D, 3, 3E, EE, ESI, -tD 

7q DATA D,EDa,ElE,lfcq,D,D,3E,lll,E51,D, -37 

aD DATA Its, 1^^,41, It, EDa, EDI, 7 b,EEq,E^q,D, - EE 

ai DATA 3E, EE, E51, D, EOl, EDa, iqi, 3E, E3q, -^a 

aE DATA E51,D,3E,EE3,ES1,D,3E,ED7,S55,ED1, -ES 

a3 DATA ^4,SDa,17a,3E,E3q,ESl,D,ltS,iq3,133,-7 

a^ DATA 17<,lt5,iq^,133,17S,3E,EE3,ESl,D,3E, -34 

as DATA ED7,E5S,EDl,13,EDa,157,3E,114,ESl,D, -3t 

at DATA 7t,EEq,E4q,D,ltS,iq4,3E,iqD,251,D, -3q 

87 DATA lt5,iq3,7E,74,7<,7<,74,3E,E14,E51, -13 

afi DATA D,17D,1D4,41,1S,3E,E14,ES1,D,7E, - It 

aq DATA 13a,3E,ElD,ESS,lD<,7t,ElD,E55,q,4a, -q 

qa DATA EDl,Sa,144,E,lDS,t,qt,ltE,E,iai, - 3D 

qi DATA iqE,7E,iai,iq4 ,i4q,iqE,iD4,i4q,iq4,EDE, -ES 

qE DATA EDa,E43,qt,3E,ES4,E51,D,144,E,133, - 3D 

q3 DATA iq4,3E,ES<,E51,0,144,E,133,iq3,qt, -43 

q4 DATA ltq,D,D,133,4E,3E,EED,E4q,D,EDl, -3q 

qS DATA 3E,EDa,q,3E,EED,E4q,D,EDl,3E,EDa, - ES 

qt DATA 14,E4,qt,3E,37,E5E,D,lD,lD,lD, -tE 

q7 DATA lD,133,4E,3E,EED,E4q,D,3E,37,E5E, -3q 

qa DATA □,S,4E,St,qt,EDl,5a,144,E,lDS, -Et 



APPENDIX H — A DO-IT-YOURSELF SUPERMON 



287 



qq DATA fl,^l,15,qt,qfc,3E,55D,E4q,D,aDl,-tE 

IDO DATA 3E,E^D,E4q,qb,lbq,0,D,l^l,D,0, -SS 

IDl DATA 1,3E,^7,EEE,D,3E,5,E5E,0,3E, -Eq 

lOE DATA E<E,E51,D,144,q,qb,3E,EED,E^q,0, -Efl 

1D3 DATA 3E, E3q,E51,D, 17 t,EEE, 174, b3,E,15<, -35 

104 DATA lfcq,t3,3E,ElD,E55,7t,SSq,E4q,D,3E, - 4fl 

IDS DATA l<3,E53,Q,EDE,EDfl,E5Q,qt,lt5,iq5,lt4, -IE 

IDt DATA iqb,5t,E33,E,17t,l,13fc,5t,EEq,iq3, -tl 

1D7 DATA 133,3D,15E,EEq,iq4,lfcfl,5,3D,qt.,3E, -41 

IDA DATA 55 / E5E, 133, 3E,lt5,iq4, 133, 33, IfcE, - EE 

IDq DATA □,D,13<,<D,lbq,147,3E,ElD,E55,lfcq, -3E 

IID DATA EE, 133, Eq,3E,lt5,E5E,0,3E, 5, E53, -E 

111 DATA □,133,iq3,13E,iq4,iqa,Eq,EDfl,E4E,lfcq, - It. 

HE DATA 14 5,3E,E10,E55,7E3,EEq,E4q,D,lt0,44, -41 

113 DATA 3E,flb,E5D,0,3E,l<3,E53,D,3S,lfl3, -E3 

114 DATA E51,D,3E,14 3,E53,D,ltE,D,D,ltl, -E5 

115 DATA iq3,3E,EQ,S53,D,7E,3S,qD,E53,D, -E5 
lit DATA lD4,3E,llE,E53,D,ltE,t,SE4,3,EDa, -43 
117 DATA lfl,lb4,31,E4D,14,lt5,4E,EQl,E3E,177, -ID 
llfi DATA iq3,17t,Efl,3E,E53,E5E,0,13t,EDa,E4E, -15 
liq DATA t,4E,144,14,lflq,54,E55,D,3E,lfl7, -3 

lEO DATA E53,D,lflq,fcD,E55,0,E4D,3,3E,lfl7, -E4 

lEl DATA E53,D,E0E,EDfi,E13,qb,3E,fl,E53,D, -45 

lEE DATA 17D,E3E,E0a,l,E0D,15E,3E,E53,E5E,n, -3q 

1E3 DATA 13a,134,Ea,3E,iqO,E51,D,lLb,Ea,qt, -47 

1E4 DATA lt5,31,5t,lb4,iq4,17D,lfc,l,13b,lDl, -53 

1E5 DATA iq3,144,l,EDD,qt,lba,74 ,14 4 ,ll,74,-El 

lEb DATA 17t,E3,EDl,34,E4D,iq,41,7,q,lEa, -t3 

1E7 DATA 74, 17D,iaq,SEq,E54, 0,17^,4, 74, 74, -5E 

lEa DATA 74,74,41,15,E0a,4,lbD,lSfl,ltq,D, - ED 

lEq DfiTA 0,17D,iaq,41,E55,D,133,4E,41,3, -tE 

13D DATA 133,31,15E,41,143,17D,15E,lt0,3,EE4, -3t 

131 DATA 13a, E4 0,11,74,144, a, 74,74, q,3E,-t, 

13E DATA 13t,EDa,E5D,EDD,13t,EDa,E4E,qt,177,iq3, -Eq 

133 DATA 3E,E53,E5a,D,lbE,l,3E,qE,E5E,D,-lt 

134 DATA iqfc,31,EDD,144,E41,lfcE,3,iqE,4,144, -la 

135 DATA E4E,qb,lba,ia5,b7,E55, 0,133,4 0, 185,-13 
13 1 DATA 131,E55,D,133,41,ltq,0,D,lbD,5, -3 

137 DATA t,41,3a,40,4E,13t,SDa,E4a,lD5,fc3,-E7 

.13a DATA 3S,ElD,E55,E0E,EDfi,E3t3,lbq,3E,EDa,ll, - It 

13q DATA ltq,13,3t,iq,lt,5,3E,ElD,E55,ltq, -30 

14 DATA 10,7t,E10,E55,3E,55,S5E,0,ltq,3, -El 

141 DATA 133,Eq,3E,EE0,E4q,0,3E,53,E50,0, -4E 



288 MACHINE LANGUAGE FOR COMMODORE MACHINES 



lAE DATA EU&,EA&,H=S,32,l33,m3,li=S,33,l33,l'=]A, -A3 

1A3 DATA 7fc,134,E5E,D,iq7,<D,E'5 0,3,35,210, -fcD 

lAA DATA a55,qfc,3E,55,E5E,D,3E,SE3,251,D, -57 

IAS DATA l^E,17,E,lbE,3,3E,47,E5E,D,7E, -43 

lAh DATA EDE,EDfl,E4q,ltE,3,lD<,5t,E33,t3,ltD, -37 

1A7 DATA 5,74,110,17,E,llD,lfc,S,13fc,EDfl, - lb 

14 fl DATA E4t,E0E,EDfi,E37,lfcE,E,3E,ED7,E55,EDl, -31 

14 H DATA 13,S4D,3D,E01,3E,E4D,E4 5,3E,EED,E54, -q 

15D DATA □,17t.,15,3E,lfl,E5E,0,lb4,iq3,13E, -q 

151 DATA iq4,133,iq3,ltq,4fl,157,lb,E,E3E,157, -47 

15E DATA lb,E,E3E,EDfl,Eiq,134,4 0,ltE,D,0, - ID 

153 DATA 134,3a,E4D,4,E3D,3fl,E4D,117,ltE,0, -q 

154 DATA □,134,Eq,lb5,3fl,3E,ED,E53,D,lfct, - 4fi 

155 DATA 4E,134,41,17D,lflfl,t7,E55,D,lflq,131, -47 
15 1 DATA E55,D,3E,iq7,E54,D,EDfi,EE7,ltE,t, -54 
157 DATA EE4/3,EDa,E5,lt4,31,E4D,El,lb5,4E, -fc3 
15fl DATA EDl,E3E,ltq,4fl,17fc,33,3E,ED3,E54,D, -3q 
15q DATA E0fl,E04,3E,ED5,E54,D,EDfl,iqq,13b,EDfi, -Efl 
ItD DATA E35,t,4E,144,ll,lflfl,b0,E55,D,lflq, -15 
Itl DATA 54,E55,D,3E,iq7,E54,D,EDfl,lfll,EDE, -1 

ItE DATA Enfi,Enq,E4n,in,3E,iqt,E54,n,EDa,i7i, -51 

lt3 DATA 3E,iqt,E54,D,EDfi,lbb,lb5,4D,iq7,Eq, -15 

lt4 DATA EDfl,ltD,3E,EE3,E51,D,lt4,31,E4D,4D, -t 

lt5 DATA lt5,41,E01,157,E0a,Et,3E,qq,E5E,D, -35 

Itt DATA 144,10,15E,EDfl,4,lt5,30,lt,lD,7b, - 40 

lt7 DATA fiD,E5E,D,EDD,SDa,S5D,lt5,3D,lt,S4b, -q 

It a DATA lt4,31,EQa,3,lfl5,iq4,D,0,14 5,iq3, -tE 

Ibq DATA 13t.,E0a,E4a,lb5,3a,145,iq3,3E,5,E53, -41 

17D DATA □,133,iq3,13S,iq4,lb0,b5,3E,at,E5D, -34 

171 DATA □,3E,143,E53,0,3E,ia3,E51,D,3E, -5t 

17E DATA 143,E53,0,7b,iqa,E53,D,lta,3E,ED3, -Eq 

173 DATA E54,Q,EDa,17,15E,E4D,14,134,Ea,ltt, -t3 

174 DATA Eq,EEl,lt,E,a,E3E,134,Eq,ltt,Ea, - to 

175 DATA 40,qt,EDl,4a,144,3,E01,71,qt,5t, -30 

i7t DATA qt,b4,E,tq,3,Eoa,a,t4,q,4a, -14 

177 DATA 34,tq,51,EDa,a,t4,q,t4,E,fcq, -50 

17a DATA 51,E0a,a,b4,q,fc4,E,tq,17q,EDa, -47 

17q DATA a,fc4,q,D,D,34,ta,51,E0a,14D, -la 

laO DATA t.a,0,D,17,34,fca,51,EDa,14D,fea, -5 

lai DATA 154,lt,34,ba,51,EDa,a,b4,q,lL, -EO 

laE DATA 34,ta,5i,EDa,a,t4,q,qa,iq,iED,-tE 

ia3 DATA ltq,0,0,33,lEq,13D,0,D,D,D, -41 

ia4 DATA aq,77,145,14t,134,74,133,157,44,41,-3q 



APPENDIX H — A DO-IT-YOURSELF SUPERMON 



289 



ifiB DATa -^4, 35, ^0,3^, an, 0,n,fla,3t,3t, - EE 

lat DATA □,D,Sa,13a,Ea,3 5,q3,13q,E7,lfcl, - ID 

Ifi? DATA 157,13a,ER,35,157,13q,Eq,lbl,D,D,-H 

laa DATA <l,E5,174,lD5,lba,E5,35,3b,fl3,E7,-fc< 

laq DATA 35,3b,a3,E5,lbl,D,D,Eb,qi,qi, -E< 

iqO DATA lb5,lD5,3b,3t,17^,174,lLa,17 3,41,0,-3 

IRl DATA D,lE^,D,D,El,15t,lD'=1,15b,lb5,lD5,-ED 

iqa DATA ^l,a3,13E,iq,5S,17,lb5,lD5,35,lfcD, -Eb 

iq3 DATA Eib,qa,qD,7E,3a,qa,i'^fi,i3fc,a^,ba,-ED 

iq/i DATA EDD,fl^,lD^,ba,53E,14a,D,D,iaD,a,-31 

iqS DATA 13E,llb,lfln,<D,110,llt,S^4,ED4,7^,ll<,-3S 

iqt DATA E4E,lt^,13a,D,D,17D,lbE,ltE,llt,llt, -11 

iq7 DATA llb,114,tfl,lD^,17a,5D,17a,D,D,34,-3D 

iqa DATA □, □,Et,Et, 3a, 3a, 114, 114, 13fc, EDO, -E7 

iqq DATA iqt,EDE,3a,7E,ta,ba,ifcE,E00,5a,5q, -35 

EDO DATA aE,77,71,aa,7fc,a3,ta,44,fc5,ED'^ , -5q 

EOl DATA E5D,D,iqi,E5D,0,qt,E50,Q,134,S50, -E5 

EDE DATA □, EE4 , E5D , , 14 , E51 , D , lit , E51 ,□ , -E3 

ED3 DATA 135 , E51 , □ , lED , E5E , □ , ItO , E53 , □ , iq4 , - iq 

ED4 DATA E53,0,EEa,E4q,Q,157,E4q,D,13q,E4q, -t3 

ED5 DATA □,13,3E,3E,3E,aD,t7,3E,3E,a3,-3 

EDt DATA aE,3E,fc5,fc7,3E,aa,aE,3S,aq,aE, - It 

E07 DATA 3E,a3,aD, -5q 

E55 DATA EDfl 

3D0 M=t3 

310 READ X:L = PEEK(M) :H = L = E55:IF H THEN L = X 

3ED V = R()L:S = (T(>t3 AND R)0 AND V) 

33D IF V THEN T = L:IF NOT S THEN R = R + 1:S = R()L 

3AD T= {T*3 + X) ANDt3 

350 IF S THEN PRINT "ERROR LINE";R:E=-1 

3tD R=L:IF NOT H GOTO 31D 

370 IF E THEN STOP 

3aD PRINT"HERE WE GO" : X =- 1 : RESTORE : B = ED4q : FOR A = l 

TO qqqq 

3qD IF X)=D THEN POKE B,X:B = B + 1 

ADO READ X:L = PEEK(M) :IF L(E55 THEN NEXT A 

AID POKE 45,lt:P0KE 4t,lt:CLR 



290 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



The Commodore 1 28 Monitor and 
SUPERMON + 

The built-in maciiine language monitor of the Commodore 128 is quite 
close to SUPERMON. With the release of the C128, a new version of 
SUPERMON (called SUPERMON + ) has been produced so as to match 
the commands and syntax of the 128's monitor. Versions are available 
for Commodore 64 (including the 1 28 in 64 mode) and for VIC-20. 

The principal features of the new monitor, as compared to SUPERMON, 
are as follows: 

— Syntax is somewhat easier. Leading zeros need not be typed on any number. 
Spacing between addresses is non-critical. 

— Conversion between number systems is built-in. The user may employ the 
following prefixes: $ for hexadecimal; + for decimal; & for octal (rarely used 
with present day microcomputers); and % for binary. Any value or address 
may be entered in any number system. If a number is typed In alone, with 
Its prefix, it will be shown converted to all other number systems. 

— When the A(assemble) command is given, the object code immediately ap- 
pears on the line just typed. 

—The disl< may be controlled, interrogated or cataloged by means of the disk 
"@" command. 

— Memory displays contain information on the ASCII equivalents of the bytes 
displayed. 

— Commands such as M (memory display) and D allow: two addresses, to 
display a specified range; one address, to display a fixed range; or no ad- 
dresses, to continue the display from that shown previously. 

Program SUPERMON -i- , for VIC-20 and Commodore 64, is not a monitor; 
it is a monitor generator that will make a machine language monitor for 
you. SUPERMON + finds a likely spot in memory and then plunks the 
MLM there so as to fit into the most suitable place. 

If you are using a VIC-20 or Commodore 64 configuration, load SUPER- 
MON-!- and type BUN. It will write an MLM for you, and call it up. Now, 
exit back to BASIC and command NEW. You do not want the MLM builder 
any more (it's done the job) and you do not want the danger of building 
two — or more — MLM's. Get rid of the generator program. Any time you 
need to use the MLM, give SYSfl. 

If you are using the Commodore 128 in its C128 mode, there's no need 
to load a monitor. Just command MONITOR and you are there. 



APPENDIX H — C128 MONITOR AND SUPERMON + 



291 



The C128 monitor and SUPERMON + use the following commands: 

R— to display (and change) registers 
M— to display (and change) memory 
S — to save memory to disk or tape 
L — to load from disk or tape 
G— to go to an ML program 
X— to exit to BASIC 
a — to assemble 
D— to disassemble 

The above commands are the only ones used within the text of the book. 
Other commands which are available are: 

F— fills memory with fixed contents: 
F IflDD IflFF □□ 

H — hunts for a memory pattern: 

H OaOO IflOO 50 D2 FF 

T — transfers a block of memory to a new location: 

T DflDD DBFF &QQO 
C — compares a block of memory to another. 

C □flOD OCDD aODD 

J— calls a subroutine directly from the monitor. 
J 0330 

@ — alone, gets the disk status report. 
@, $□ — gets the disk directory. 

@, SO : SAMPLE— sends a command to the disk (in the example, scratch file 
SAMPLE). 

The @ symbol may be followed by a number to reference a drive other 
than unit 8. 



I 



lA Chip 
Information 

Tfie following material has been adapted from manufacturer's specifica- 
tions. The information is not essential to machine language programming, 
but can be a great help for further study. Some of these specifications are 
not widely published and contain "hard to get" information. 

6520 PI a, peripheral interface adaptor 
6522 VIA, versatile interface adaptor 

6525 TPA, tri port adaptor 

6526 CIA, complex interface adaptor 
6545 CRTC, CRT controller 

6560 VIC video interface chip 
6566 VIC-E video interface chip 
6581 SID sound interface chip 

[Essentially manufacturer's specs, less hardware details] 



293 



294 MACHINE LANGUAGE FOR COMMODORE MACHINES 



6520 Peripheral Interface Adaptor (PIA) 

The 6520 is an I/O device wliicli acts as an interface between tlie micro- 
processor and peripherals such as printers, displays, keyboards, etc. The 
prime function of the 6520 is to respond to stimulus from each of the two 
worlds it is serving. On the one side, the 6520 is interfacing with peripherals 
via two eight-bit bi-directional peripheral data ports. On the other side, the 
device interfaces with the microprocessor through an eight-bit data bus. 
In addition to the lines described above, the 6520 provides four interrupt 
input/peripheral control lines and the logic necessary for simple, effective 
control of peripheral interrupts. 



MICRO 

PROCESSORS -< 
650 X 



8 BIT \ 
DATA ) 
BUS / 



( 



CONTROL 



( control) 



6520 



8 BIT 
DATA 
PORT 



8 BIT 
DATA 
PORT 



PERIPHERAL 
DEVICES- 
SPRINTERS, 
DISPLAYS, 
ETC. 



CONTROL ) 



Figure 1.1 



The functional configuration of the 6520 is programmed by the micro- 
processor during systems initialization. Each of the peripheral data lines 
is programmed to act as an input or output and each of the four control/ 
interrupt lines may be programmed for one of four possible control modes. 
This allows a high degree of flexibility in the overall operation of the in- 
terface. 

Data Input Register 

When the microprocessor writes data into the 6520, the data which ap- 
pears on the data bus is latched into the Data Input Register. It is then 
transferred into one of six internal registers of the 6520. This assures that 
the data on the peripheral output lines will not "glitch," i.e., the output lines 
will make smooth transitions from high to low or from low to high and the 
voltage will remain stable except when it is going to the opposite polarity. 



APPENDIX I 



295 



Control Registers fCRA and CRB) 

Figure 1.2 illustrates tlie bit designation and functions in the Control Reg- 
isters. Tlie Control Registers allow the microprocessor to control the op- 
eration of the interrupt lines (CAl, CAE, CBl, CBE), and peripheral 
control lines (CR2, CBE). A single bit in each register controls the ad- 
dressing of the Data Direction Registers (DDRA, DDRB) and the Output 
Registers, {0R&, ORB) discussed below. In addition, two bits (bit Ed and 
7 ) are provided in each control register to indicate the status of the i nterrupt 
input li nes (CAl, CAS, CBl, CB2). These interrupt status bits (IRQA, 
IRQB) are normally interrogated by the microprocessor during the inter- 
rupt service program to determine the source of an acti ve interrupt . These 
are the interrupt lines which drive the interrupt input (IRQ, NMI) of the 
microprocessor. The other bits in CRA and GRB are described in the 
discussion of the interface to the peripheral device. 

The various bits in the control registers will be accessed many times during 
a program to allow the processor to enable or disable interrupts, change 
operating modes, etc. as required by the peripheral device being con- 
trolled. 

Data Direction Registers fDDRA, DDRB; 

The Data Direction Registers allow the processor to program each line in 
the 8-bit Peripheral I/O port to act as either an input or an output. Each 
bit in DDR A controls the corresponding lines in the Peripheral A port and 
each bit in DDRB controls the corresponding line in the Peripheral B port. 
Placing a " " in the Data Direction Register causes the corresponding 
Peripheral I/O line to act as an input. A " 1 " causes it to act as an output. 

The Data Direction Registers are normally programmed only during the 
system initialization routine which is performed in response to a Reset 
signal. However, the contents of these registers can be altered during 
system operation. This allows very convenient control of some peripheral 
devices such as l<eyboards. 

Periplieral Output Registers fOR A, ORB; 

The Peripheral Output Registers store the output data which appears on 
the Peripheral I/O port. Writing an "0" into a bit in OR A causes the 
corresponding line on the Peripheral A port to go low (< . 4 V) if that 
line is programmed to act as an output. A " 1 " causes the corresponding 
output to go high. The lines of the Peripheral B port are controlled by ORB 
in the same manner. 



296 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Interrupt Status Control 

The four interrupt/peripheral control lines (CRl, CRE, CBl, CBE) are 
controlled by the Interrupt Status Control (A, B). This logic interprets the 
contents of the corresponding Control Register, detects active transitions 
on the interrupt inputs and performs those operations necessary to assure 
proper operation of these four peripheral interface lines. 



Reset (R'ES) 

The active low Reset line resets the contents of all 6520 registers to a 
logic zero. This line can be used as a power-on reset or as a master reset 
during system operation. 



Interrupt Request Une fl R Q A, I R Q Bj 

The active low Interrupt Request lines (IRQR and IRQB) act to interrupt 
the microprocessor either directly or through external interrupt priority cir- 
cuitry. 

Each Interrupt Request line has two interrupt flag bits which can cause 
the Interrupt Request line to go low. These flags are bits t and 7 in the 
two Control Registers. These flags act as the link between the peripheral 
interrupt signals and the microprocessor interrupt inputs. Each flag has a 
corresponding interrupt disable bit which allows the processor to enable 
or disable the interrupt from each of the four interrupt inputs (CRl, CAE, 
CBl, CBE). 

The four interrupt flags are set by active transitions of the signal on the 
interrupt input (CRl, CRE, CBl, CBE). Controlling this active transition 
is discussed in the next section. 



Control of IRQA 

Control Register R bit 7 is always set by an active transition of the CRl 
interrupt input signal. Interrupting from this flag can be disabled by setting 
bit □ in the Control Register R (CRR) to a logic □. Likewise, Control 
Register R bit t can be set by an active transition of the CRE interrupt 
input signal. Interrupting from this flag can be disabled by setting bit 3 in 
the Control Register to a logic □. 

Both bit t and bit 7 in CRR are reset by a "Read Peripheral Output 
Register A" operation. This is defined as an operation in which the pro- 
cessor reads the Peripheral A I/O port. 



APPENDIX I 



297 



Control of IRQB 

Control of IRQB is perfo rmed in exactly the same manner as that de- 
scribed above for IRQR. Bit 7 in CRB is set by an active transition on 
CBl; interrupting from this flag is controlled by CRB bit 0. Lil<ewise, bit 
t in CRB is set by an active transition on CBE; interrupting from this flag 
is controlled by CRB bit 3. 

Also, both bit L and bit 7 are reset by a "Read Peripheral B Output 
Register" operation. 

Summary 

IRQAgoeslowwhen CRa-7 = 1 and CRfi-D = lor when CRR-fc 
= 1 and CRft-3 = 1. 

IRQB goes low when CRB -7 = 1 and CRB -0 = 1 or when CRB - 1 

= 1 and CRB -3 = 1. 

It should be stressed at this point that the flags act as the link between 
the peripheral interrupt signal and the processor interrupt inputs. The in- 
terrupt disable bits allow the processor to control the interrupt function. 

Peripheral I/O Ports 

Each of the Peripheral I/O lines can be programmed to act as an input or 
an output. This is accomplished by setting a " 1 " in the corresponding 
bit in the Data Direction Register for those lines which are to act as outputs. 
A " □ " in a bit of the Data Direction Register causes the corresponding 
Peripheral I/O lines to act as an input. 

Interrupt Input/ Peripheral Control Lines (CAl, 
CAE, CBl, CBE 

The four interrupt inpuf peripheral control lines provide a number of special 
peripheral control functions. These lines greatly enhance the power of the 
two general purpose interface ports (Pan-PR7, PBD-PB7). 

Peripheral A Interrupt Input/ Peripheral Control 
Unes (CM, CA2) 

Ckl is an interrupt input only. An active transition of the signal on this 
input will set bit 7 of the Control Register a to a logic 1 . The active transition 
can be programmed by the microprocessor by setting a " Q " in bit 1 of 



298 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



the CRA if the interrupt flag (bit 7 of CBA) is to be set on a negative 
transition of the C AI signal or a " 1 " if it is to be set on a positive transition. 

Setting the interrupt flag will interrupt the processor through IRQA if bit 
□ of CR a is a 1 as described previously. 

CAE can act as a totally independent interrupt input or as a peripheral 
control output. As an input (CRA , bit 5 = D) it acts to set the interrupt 
flag, bit t of CRA, to a logic 1 on the active transition selected by bit A 
of CRA. 

These control register bits and interrupt inputs serve the same basic func- 
tion as that described above for CAl. The input signal sets the interrupt 
flag which serves as the link between the peripheral device and the pro- 
cessor interrupt structure. The interrupt disable bit allows the processor 
to exercise control over the system interrupts. 

In the Output mode (CR A , bit 5 = 1), CA2 can operate independently 
to generate a simple pulse each time the microprocessor reads the data 
on the Peripheral A I/O port. This mode is selected by setting CRA, bit A 
to a "□" and CRA, bit 3 to a "1". This pulse output can be used to 
control the counters, shift registers, etc. which mal<e sequential data avail- 
able on the Peripheral input lines. 

A second output mode allows CAE to be used in conjunction with CAl 
to "handshake" between the processor and the peripheral device. On the 
A side, this technique allows positive control of data transfers from the 
peripheral device into the microprocessor. The CAl input signals the 
processor that data is available by interrupting the processor. The pro- 
cessor reads the data and sets CAE low. This signals the peripheral device 
that it can make new data available. 

The final output mode can be selected by setting bit ^ of CRA to a 1. In 
this mode, CAE is a simple peripheral control output which can be set 
high or low by setting bit 3 of CRA to a 1 or a □ respectively. 

Peripheral B Interrupt Input/Peripheral Control 
Unes (CBl, CB Ej 

CBl operates as an interrupt input only in the same manner as CAl. Bit 
7 of CRB is set by the active transition selected by bit of CRB. Likewise, 
the CBE input mode operates exactly the same as the CAE input modes. 
The CBE output modes, CRB, bit 5 = 1, differ somewhat from those 
of CAE. The pulse output occurs when the processor writes data into the 
Peripheral B Output Register. Also, the "handshaking" operates on data 
transfers from the processor into the peripheral device. 



APPENDIX I 



299 





7 


6 


5 4 3 


2 


1 (J 


CRA 


IRQA1 


IRQA2 


CA2 CONTROL 


DDRA 
ACCESS 


CA1 CONTROL 
, * . 








, ^ . 












7 


6 


5 4 3 


2 


1 


CRB 


IRQBl 


IRQB2 


CB2 CONTROL 

A 


DDRB 
ACCESS 


CB2 CONTROL 
, * ^ 








f \ 





Figure L2 

6545-1 CRT Controller (CRTC) 

Concept 

The 6545-1 is a CRT Controller intended to provide capability for inter- 
facing the 6500 microprocessor family to CRT or TV-type raster scan 
displays. 

Horizontal Total (RO) 

This 8-bit register contains the total of displayed and non-displayed char- 
acters, minus one, per horizontal line. The frequency of HSYNC is thus 
determined by this register. 

Horizontal Displayed (R1) 

This 8-bit register contains the number of displayed characters per hori- 
zontal line. 

Horizontal Sync Position (R2) 

This 8-bit register contains the position of the HSYNC on the horizontal 
line, in terms of the character location number on the line. The position 
of the HSYNC determines the left-to-right location of the displayed text on 
the video screen. In this way, the side margins are adjusted. 



300 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Horizontal and Vertical SYNC Widths (R3) 

This 8-bit register contains the widths of both HSYNC and VSYNC, as 
follows: 



7 


6 


5 


4 


3 


2 


1 






8 4 2 1 8 4 2 1 

' 1 ' ' 1 ' 

VSYNC |WIDTH* HSYNC| WIDTH 

(NUMBER OF SCAN LINES) (NUMBER OF CHARACTER 

CLOCK TIMES) 

*IF BITS 4-7 ARE ALL "0"; THEN VSYNC WILL BE 16 SCAN LINES WIDE. 

Control of these parameters allows the 6545-1 to be interfaced to a variety 
of CRT monitors, since the HSYNC and VSYNC timing signals may be 
accommodated without the use of external one-shot timing. 



Vertical Total (R4) 

The Vertical Total Register is a 7-bit register containing the total number 
of character rows in a frame, minus one. This register, along with R5, 
determines the overall frame rate, which should be close to the line fre- 
quency to ensure flicker-free appearance. If the frame time is adjusted to 
be longer than the period of the line frequency, then RES may be used 
to provide absolute synchronism. 



Vertical Total Adjust (R5) 

The Vertical Total Adjust Register is a 5-bit write only register containing 
the number of additional scan lines needed to complete an entire frame 
scan and is intended as a fine adjustment for the video frame time. 



Vertical Displayed (R6) 

This 7-bit register contains the number of displayed character rows in each 
frame. In this way, the vertical size of the displayed text is determined. 



APPENDIX I 



301 



vt 
'5) 



CO 

to 
1^ 



oc 

5 



Q 



■O 

o 



o 

E 
a 



0) 

to 
o 



DC 2 



o 
X 



n 
X 



o8 



□ »- 
CO O 



idVH "Jt^ -JJ^ *^t^ -JT^i 



of 
2 Q CO o 

N N N 5 

O O O CO 
X X X > 



O T- OJ CO 
DC CC DC DC 



■ X ■ ■ ■ X m 

■ X ■ ■ ■ X m 

X X X X ■ X X 



(0 CO 

o 0) o o 

OC O DC DC 

d □ d d 

CO _ CO CO 

i— d 1— i— 

CO (0 CO CO 

£ (3 £ x: 

O CO O O 

=fe * * * 



=i g 

o c 
CO g 

* CO 



CO 



c 
o 



> > 



CO 

0) o ^ 

CO ^ 

"5_ " <= 

. . fl) c 

■c -o § 

0) O o 

> 2 CO O 



> 



- 0) iS 
c CO 

o 
CO 



o 

in CD h- CO o) 1- 
GC CC X DC DC DC DC 



X ■ 

X X 
X X 



X ■ X 
X ■ X 



c 

CO 

o 
CO 



X 3; 

T3 T3 
T3 T3 _ 

< < § 

■c -c s 

"O CO CO CO 

iS w 55 £ 
o w w o 

CO Q-Q. 2 
3 CO (0 3 

O Q b o 



o ci) d) 
w DC DC 

1? = 

2 £ £ 
o □ □ 



1- cj CO lo to 
E X X E £ E E 



CO 

CO 
3 
Si 

CO 

15 

T3 
0) 



CD 
> 



o 
c 

CO 
(D 
O 
TJ 

JZ 

o 
5 



CO 
X 



Q. 
CD 
O 
X 




I 

5 

(0 . 

CO ® 

.iS CO 

^ 
CO ^ 



is CO 

o> •« 
c 2 



CO Q. 
O 
DC j= 
*J — 

*- s ■§ 

^ CO ^ 
to 3 - 
.£ c CO 

3 O 
CO CO L. 

S £ 

^li 

« w 5S " 
© = 

B Q C3 « 

Z p X 



302 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Vertical Sync Position (R7) 

This 7-bit register is used to select the character row time at which the 
VSYNC pulse is desired to occur and, thus, is used to position the dis- 
played text in the vertical direction. 

MoQfe Control (R8) 

This register is used to select the operating modes of the 6545-1 and is 
outlined as follows: 



7 


6 


5 


4 


3 


2 1 1 






-INTERFACE MODE CONTROL 



BIT 


OPERATION 


1 





X 





NON INTERLACE 


X 


1 


INVALID (DO NOT USE) 



VIDEO DISPLAY RAM ADDRESSING 
"0" FOR STRAIGHT BINARY 
"1" FOR ROW/COLUMN 

MUST PROGRAM TO "0" 



DISPLAY ENABLE SKEW 
"0" FOR NO DELAY 
"1" TO DELAY DISPLAY ENABLE 
ONE CHARACTER TIME 



' CURSOR SKEW 

"0" FOR NEW DELAY 
"1" TO DELAY CURSOR ONE 
CHARACTER TIME 

[]-NOT USED 

Figure 1.3 

Scan Line (R9) 

This 5-bit register contains the number of scan lines per character row, 
including spacing. 



APPENDIX I 



303 



Cursor Start (R10) and Cursor End (R11) 

These 5-bit registers select the starting and ending scan lines for the 
cursor. In addition, bits 5 and 6 of R1 are used to select the cursor mode, 
as follows: 




CURSOR MODE 



No Blinking 
No Cursor 

Blink at 1/16 field rate 
Blink at 1/32 field rate 



Note that the ability to program both the start and end scan line for the 
cursor enables either block cursor or underline to be accommodated. 
Registers R14 and R15 are used to control the character position of the 
cursor over the entire 16K address field. 

Display Start Address High (R12) and Low 
(R13) 

These registers together comprise a 14-bit register whose contents is the 
memory address of the first character of the displayed scan (the character 
on the top left of the video display, as in Figure 1). Subsequent memory 
addresses are generated by the 6545-1 as a result of CCLK input pulses. 
Scrolling of the display is accomplished by changing R12 and R13 to the 
memory address associated with the first character of the desired line of 
text to be displayed first. Entire pages of text may be scrolled or changed 
as well via R12 and R13. 

Cursor Position l-ligli (R14) and Low (R15) 

These registers together comprise a 1 4-bit register whose contents is the 
memory address of the current cursor position. When the video display 
scan counter (MA lines) matches the contents of this register, and when 
the scan line counter (RA lines) falls within the bounds set by R10 and 
R1 1 , then the CURSOR output becomes active. Bit 5 of the Mode Control 
Register (R8) may be used to delay the CURSOR output by a full CCLK 
time to accommodate slow access memories. 

LPEN Higli (R16) and Low (R17) 

These registers together comprise a 14-bit register whose contents is the 
light pen strobe position, in terms of the video display address at which 



304 MACHINE LANGUAGE FOR COMMODORE MACHINES 



the strobe occurred. When the LPEN input changes from low to high, then, 
on the next negative-going edge of CCLK, the contents of the internal 
scan counter is stored in registers R16 and R17. 

6560 (VIC) Video Interface Chip 

The 6560 Video Interface Chip (VIC) is designed for color video graphics 
applications such as low cost CRT terminals, biomedical monitors, control 
system displays and arcade or home video games. It provides all of the 
circuitry necessary for generating color programmable character graphics 
with high screen resolution. VIC also incorporates sound effects and A/D 
converters for use in a video game environment. 

Features 

• Fully expandable system with a 16K byte address space 

• System uses industry standard 8 bit wide ROMS and 4 bit wide RAMS 

• Mask programmable sync generation, NTSC-6560, PAL-6561 

• On-chip color generation (16 colors) 

• Up to 600 independently programmable and movable background locations 
on a standard TV 

• Screen centering capability 

• Screen grid size up to 192 Horizontal by 200 Vertical dots 

• Two selectable graphic character sizes 

• On-chip sound system including: 

a) Three independent, programmable tone generators 

b) White noise generator 

c) Amplitude modulator 

• Two on-chip 8 bit A/D converters 

• ON-chip DMA and address generation 

• No CPU wait states or screen hash during screen refresh 

• Interlaced/Non-interlaced switch 

• 16 addressable control registers 

• Light gun/pen for target ^ames 

• 2 modes of color operation 

A: Interlace mode: A normal video frame is sent to the TV 60 times each 
second. Interlace mode cuts the number of repetitions in half. When used 
with multiplexing equipment, this allows the VIC picture to be blended with 
a picture from another source. 



APPENDIX I 



305 



To turn off: POKE 36864, PEEK(36864) AND 127 
To turn on: POKE 36864, PEEK(36864) OR 128 

B: Screen origin— horizontal: This determines the positioning of the 
image on the TV screen. The normal value is 5. Lowering the value moves 
the screen to the left, and increasing it moves the image to the right. 

To change value: POKE 36864, PEEK(36864) AND 128 OR X 



LOC 
Hex 


START VALUE-5K VIC 


Bit 

Function 


Binary 


Decimal 


9000 


00000101 


5 


ABBBBBBB 


9001 


00011001 


25 


CCCCCCCC 


yuu<; 


10010110 


150 


tlL/UUULJlJLJ 


9003 


V0101110 


46 or 174 


GEEEEEEF 


9004 


vwvvwv 


V 


GGGGGGGG 


9005 


11110000 


240 


HHHHIIII 


9006 


00000000 





JJJJJJJJ 


9007 


00000000 





KKKKKKKK 


9008 


11111111 


255 


LLLLLLLL 


9009 


11111111 


255 


MMiyiMMMMM 


900A 


00000000 





NRRRRRRR 


900B 


00000000 





OSSSSSSS 


900C 


00000000 







900D 


00000000 





QUUUUUUU 


900E 


00000000 





wwwwvwv 


900F 


00011011 


27 


XXXXYZZZ 



A: 


Interlace mode: 0=off, 


N: 


Bass sound switch 




1 =on 


0: 


Alto sound switch 


B: 


Screen origin — horizontal 


P: 


Soprano sound switch 


C: 


Screen origin — vertical 


Q: 


Noise switch 


D: 


Number of video columns 


R: 


Bass Frequency 


E: 


Number of video rows 


S: 


Alto Frequency 


F: 


Character size: 


T: 


Soprano Frequency 




= 8x8, 1 =8x16 


U: 


Noise Frequency 


G: 


Raster value 


V: 


Loudness of sounds 


H: 


Screen memory location 


W: 


Auxiliary color 


1: 


Character memory location 


X: 


Screen color 


J: 


Light pen — horizontal 


Y: 


Reverse mode = on, 


K: 


Light pen — vertical 




1=off 


L: 


Paddle 1 


Z: 


Border color 


M: 


Paddle 2 







306 MACHINE LANGUAGE FOR COMMODORE MACHINES 



C: Screen origin— vertical: This determines tlie up-down placement of 
the screen image. The normal value is 25. Lowering this causes the screen 
to move up by 2 rows of dots for each number lowered, and raising it 
moves the screen down. 

To change value: POKE 36865, X 

D: Number of video columns: Normally, this is set to 22. Changing this 
will change the display accordingly. Numbers over 27 will give a 27 column 
screen. The cursor controls are based on a fixed number of 22 columns, 
and changing this number makes the cursor controls misbehave. 

To change: POKE 36866, PEEK(36866) AND 128 OR X. 

E: Number of video rows: The number of rows may range from to 23. 
A larger number of rows causes garbage to appear on the bottom of the 
screen. 

To change: POKE 36867, PEEK(36867) AND 129 OR (X*2) 

F: Character size: This bit determined the size of the matrix used for 
each character. A here sets normal mode, in which characters are 8 by 
8 dots. A 1 sets 8 by 16 mode, where each character is now twice as tall. 
8 by 16 mode is normally used for high resolution graphics, where it is 
likely to have many unique characters on the screen. 

To set 8 by 8 mode: POKE 36867, PEEK(36867) AND 254 

To set 8 by 16 mode: POKE 36867, PEEK(36867) OR 1 

G: Raster value: This number is used to synchronize the light pen with 
the TV picture. 

H: Screen memory location: This determines where in memory the VIC 
keeps the image of the screen. The highest bit in location 36869 must be 
a 1. Bits 4-6 of location 36869 are bits 10-12 of the screen's address, 
and bit 7 of location 36866 is bit 9 of the address of the screen. To 
determine the location of the screen, use the formula: 

S = 4* (PEEK(36866) AND 128) + 64* (PEEK(36869) AND 112) 

Note that bit 7 of location 36866 also determines the location of color 
memory. If this bit is a 0, color memory starts at location 37888. If this bit 
is a 1 , color memory begins at 38400. Here is a formula for this: 

C = 37888 + 4* (PEEK(36866) AND 128) 

I: Character memory location: This determines where information on 
the shapes of characters are stored. Normally this pointer is to the char- 
acter generator ROM, which contains both the upper case/graphics or the 



APPENDIX I 



307 



upper/lower case set. However, a simple POKE command can change 
this pointer to a RAM location, allowing custom character sets and high 
resolution graphics. 

To change: POKE 36869, PEEK(36869) AND 240 OR X 
(See chart on next page.) 

J: Light pen horizontal: This contains the latched number of the dot 
under the light pen, from the left of the screen. 

K: Light pen vertical: The latched number of the dot under the pen, 
counted from the top of the screen. 



X 


Location 


Contents 


Value 


HEX 


Decimal 





8000 


32768 


Upper case normal characters 


1 


8400 


33792 


Upper case reversed characters 


2 


8800 


34816 


Lower case normal characters 


3 


8000 


35840 


Lower case reversed characters 


4 


9000 


36864 


unavailable 


5 


9400 


37888 


unavailable 


6 


9800 


38912 


VIC chip-unavailable 


7 


9C00 


39936 


ROM-unavailable 


8 


0000 





unavailable 


9 






unavailable 


10 






unavailable 


11 






unavailable 


12 


1000 


4096 


RAM 


13 


1400 


5120 


RAM 


14 


1800 


6144 


RAM 


15 


1000 


7168 


RAM 



L: Paddle X: This contains the digitized value of a variable resistance 
(game paddle). The number reads from to 255. 

M: Paddle Y: Same as Paddle X, for a second analog input. 

N: Bass switch: If this bit is a 0, no sound is played from Voice 1. A 1 
in this bit results in a tone determined by Frequency 1 . 

To turn on: POKE 36874, PEEK(36874) OR 128 

To turn off: POKE 36874, PEEK(36874) AND 127 

O: Alto switch: See Bass switch. 



308 MACHINE LANGUAGE FOR COMMODORE MACHINES 



P: Soprano switch: See Bass switch. 
Q: Noise switch: See Bass switch. 

R: Bass Frequency: This is a value corresponding to the frequency of 
the tone being played. The larger the number, the higher the pitch of the 
tone. 

The actual frequency of the sound in cycles per second (hertz) is deter- 
nnined by the following formula: 

Clock 

Frequency = ^^^^ 

X is the number from to 127 that is put into the frequency register. If X 
is 1 27, then use - 1 for X in the formula. The value of Clock comes from 
the following table: 



Register 


NTSC (US TV's) 


PAL (European) 


36874 


3995 


4329 


36875 


7990 


8659 


36876 


15980 


17320 


36877 


31960 


34640 



To set: POKE 36874, PEEK(36874) AND 128 OR X 

S: Alto Frequency: This is a value corresponding to the frequency of the 
tone being played. The larger the number, the higher the pitch of the tone. 

T: Soprano Frequency: This is a value corresponding to the frequency 
of the tone being played. The larger the number, the higher the pitch of 
the tone. 

To set: POKE 36876, PEEK(36876) AND 128 OR X 

U: Noise Frequency: This is a value corresponding to the frequency of 
the noise being played. The larger the number, the higher the pitch of the 
noise. 

To set: POKE 36877, PEEK(36877) AND 128 OR X 

V: Loudness of sounds: This is the volume control for all the sounds 
playing. is off and 15 is the loudest sound. 

To set: POKE 36878, PEEK(36878) AND 240 OR X 

W: Auxiliary color: This register holds the color number of the auxiliary 
color. The value can be from to 15. 



APPENDIX I 



309 



To set: POKE 36878, PEEK(36878) AND 15 OR (16*X) 

X: Screen color: A number from to 15 sets the color of the screen. 

To set: POKE 36879, PEEK(36879) AND 15 OR (X*16) 

Y: Reverse mode: A 1 in this bit indicates normal characters, and a 
here causes all characters to be displayed as if reversed. 

To turn on reverse mode: POKE 36879, PEEK(36879) AND 247 

To turn off reverse mode: POKE 36879, PEEK(36879) OR 8 

Z: Border color: A number from to 7 sets the color of the screen. 

To set: POKE 36879, PEEK(36879) AND 248 OR X 

6522 Versatile Interface Adapter (VIA) 

The 6522 Versatile interface Adapter (VIA) provides two peripheral ports 
with input latching, two powerful interval timers, and a serial-to-parallel/ 
parallel-to-serlal shift register. 



6522 Versatile Interface Adapter Description 



ADDRESS 


DESCRIPTION 


REGISTER 


9110 


Port B 


AAAAAAAA 


9111 


Port A (with handshaking) 


BBBBBBBB 


9112 


Data Direction B 


CCCCCCCC 


9113 


Data Direction A 


DDDDDDDD 


9114 


Timer #1 , low byte 


EEEEEEEE 


9115 


Timer #1, high byte 


FFFFFFFF 


9116 


Timer #1 , low byte to load 


GGGGGGGG 


9117 


Timer #1 , high byte to load 


HHHHHHHH 


9118 


Timer #2, low byte 


IIIIIIII 


9119 


Timer #2, high byte 


JJJJJJJJ 


911A 


Shift Register 


KKKKKKKK 


911B 


Auxiliary Control 


LLMNNNOP 


911C 


Peripheral Control 


QQQRSSST 


91 1D 


Interrupt Flags 


UVWXYZab 


911E 


Interrupt Enable 


cedf ghij 


911F 


Port A (no handshaking) 


kkkkkkkk 



310 MACHINE LANGUAGE FOR COMMODORE MACHINES 



PORT A I/O REGISTER 

These eight bits are connected to the eight pins which make up port A. 
Each pin can be set for either input or output. 

Input latching is available on this port. When latch mode is enabled the 
data in the register freezes when the CB1 interrupt flag is set. The register 
stays latched until the interrupt flag is cleared. 

Handshaking is available for output from this port. CB2 will act as a DATA 
READY SIGNAL. This must be controlled by the user program. CB1 acts 
as the DATA ACCEPTED signal, and must be controlled by the device 
connected to the port. When DATA ACCEPTED is sent to the 6522, the 
DATA READY line is cleared, and the interrupt flag is set. 

PORT B I/O REGISTER 

These eight bits are connected to the eight pins which make up port B. 
Each pin can be set for either input or output. Handshaking is available 
for both read and write operations. Write handshaking is similar to that on 
PORT B. Read handshaking is automatic. The CA1 input pin acts as a 
DATA READY signal. The CA2 pin (used for output) is used for a DATA 
ACCEPTED signal. When a DATA READY signal is received a flag is set. 
The chip can be set to generate an interrupt or the flag can be polled 
under program control. The DATA ACCEPTED signal can either be a 
pulse or a DC level. It is set low by the CPU and cleared by the DATA 
READY signal. 

DATA DIRECTION FOR PORT B 

This register is used to control whether a particular bit in PORT B is used 
for input or output. Each bit of the data direction register (DDR) is asso- 
ciated with a bit of port B. If a bit in the DDR is set to 1 , the corresponding 
bit of the port will be an OUTPUT. If a bit in the DDR is 0, the corresponding 
bit of the port will be an INPUT. 

For example, if the DDR is set to 7, port B will be set up as follows: 



BITS NUMBER DDR PORT B FUNCTION 

1 OUTPUT 

1 1 OUTPUT 

2 1 OUTPUT 

3 INPUT 

4 INPUT 

5 INPUT 

6 INPUT 

7 INPUT 



APPENDIX I 



311 



DATA DIRECTION REGISTER FOR PORT A 

This is similar to tlie DDR for port B, except tliat it worl<s on PORT A. 

E,F,G,H: TIMER CONTROLS 

Tliere are two timers on tlie 6522 chip. The timers can be set to count 
down automatically or count pulses received by the VIA. The mode of 
operation is selected by the Auxiliary Control register. 

TIMER T1 on the 6522 consists of two 8-bit latches and a 16-bit counter. 
The various modes of the TIMER are selected by setting the AUXILIARY 
CONTROL REGISTER (ACR). The latches are used to store a 16-bit data 
word to load into the counter. Loading a number into the latches does not 
affect the count in progress. 

After it is set, the countfer yyill begin decrementing at 1 MHz. When the 
counter reaches zero, an interrupt flag will be set, and the IRQ will go low. 
Depending on how the TIMER is set, either further interrupts will be dis- 
abled, or it will automatically load the two latches into the counter and 
continue counting. The TIMER can also be set to invert the output signal 
on a peripheral pin each time it reaches zero and resets. 

The TIMER locations work differently on reading and writing. 
WRITING TO THE TIMER: 

E: Write into the low order latch. This latch can be loaded into the low 
byte of the 1 6-bit counter. 

F: Write into the high order latch, write into the high order counter, trans- 
fer low order latch into the low order counter, and reset the TIMER T1 
interrupt flag. In other words, when this location is set the counter is loaded. 

G: Same as E. 

H: Write into the high order latch and reset the TIMER T1 interrupt flag. 
READ TIMER T1 

E: Read the TIMER T1 low order counter and reset the TIMER T1 in- 
terrupt flag. 

F: Read the TIMER T1 high order counter. 
G: Read the TIMER T1 low order latch. 
H: Read the TIMER T1 high order latch. 



312 MACHINE LANGUAGE FOR COMMODORE MACHINES 



TIMER T2 

This TIMER operates as an interval timer (in one-shot mode), or as a 
counter for counting negative pulses on PORT B pin 6. A bit in the ACR 
selects which mode TIMER T2 is in. 



WRITING TO TIMER T2 

I: Write TIMER T2 low order byte of latch. 

J: Write TIMER T2 high order counter byte, transfer low order latch to 
low order counter, clear TIMER T2 interrupt flag. 

READING TIMER T2 

I: Read TIMER T2 low order counter byte, and clear TIMER T2 interrupt 
flag. 



K: SHIFT REGISTER 

A shift register is a register which will rotate itself through the CB2 pin. 
The shift register can be loaded with any 8-bit pattern which can be shifted 
out through the CB1 pin, or input to the CB1 pin can be shifted into the 
shift register and then read. This makes it highly useful for serial to parallel 
and parallel to serial conversions. 

The shift register is controlled by bits 2-4 of the Auxiliary Control register. 



L,M,N,0,P: AUXILIARY CONTROL REGISTER 

L: TIMER 1 CONTROL 

BIT # 7 6 

One-shot mode (output to PB7 disabled) 

1 Free running mode (output to PB7 disabled) 

1 One-shot mode (output to PB7 enabled) 

1 1 Free running mode (output to PB7 enabled) 



M: TIMER 2 CONTROL 

TIMER 2 has 2 modes. If this bit is 0, TIMER 2 acts as an interval timer 
in one-shot mode. If this bit is 1 , TIMER 2 will count a predetermined 
number of pulses on pin PB6. 



APPENDIX I 



313 



N: SHIFT REGISTER CONTROL 



BIT # 



4 


3 


2 




n 


n 


yj 


euicT REGISTER DISABLED 


n 





1 

1 


SHIFT IN ^FROM CB1^ UNDER CONTROL OF 








TIMER 2 





1 





SHIFT IN UNDER CONTROL OF SYSTEM CLOCK 








PIJLSFS 





1 


1 


SHIFT IN UNDER CONTROL OF EXTERNAL 








CLOCK PULSES 


1 








FREE RUN MODE AT RATE SET BY TIMER 2 


1 





1 


SHIFT OUT UNDER CONTROL OF TIMER 2 


1 


1 





SHIFT OUT UNDER CONTROL OF SYSTEM 








CLOCK PULSES 


1 


1 


1 


SHIFT OUT UNDER CONTROL OF EXTERNAL 



CLOCK PULSES 



O: PORT B LATCH ENABLE 

As long as this bit is 0, the PORT B register will directly reflect the data 
on the pins. 

If this bit is set to one, the data present on the input pins of PORT A will 
be latched within the chip when the CB1 INTERRUPT FLAG is set. As 
long as the CB1 INTERRUPT FLAG is set, the data on the pins can change 
without affecting the contents of the PORT B register. Note that the CPU 
always reads the register (the latches) rather than the pins. 

Input latching can be used with any of the input or output modes available 
for CB2. 



P: PORT A LATCH ENABLE 

As long as this bit is 0, the PORT A register will directly reflect the data 
on the pins. 

If this bit is set to one, the data present on the input pins of PORT A will 
be latched within the chip when the CA1 INTERRUPT FLAG is set. As 
long as the CA1 INTERRUPT FLAG is set, the data on the pins can change 
without affecting the contents of the PORT A register. Note that the CPU 
always reads the register (the latches) rather than the pins. 

Input latching can be used with any of the input or output modes available 
for CA2. 



374 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



Q,R,S,T THE PERIPHERAL CONTROL REGISTER 

0: CB2 CONTROL 

O Q O 

BIT# 7 6 5 



1 

1 

1 1 

1 
1 1 
1 1 

1 1 1 

INTERRUPT INPUT MODE: 

The CB2 interrupt flag (IFR bit 3) will be set on a negative (high-to-low) 
transition on the CB2 input line. The CB2 interrupt bit will be cleared on 
a read or write to PORT B. 

INDEPENDENT INTERRUPT INPUT MODE: 

As above, the CB2 interrupt flag will be set on a negative transition on 
the CB2 input line. However, reading or writing to PORT B does not clear 
the flag. 

INPUT MODE: 

The CB2 interrupt flag (IFR bit 3) will be set on a positive (low-to-high) 
transition of the CB2 line. The CB2 flag will be cleared on a read or write 
of PORT B. 

INDEPENDENT INPUT MODE: 

As above, the CB2 interrupt flag will be set on a positive transition on the 
CB2 line. However, reading or writing PORT B does not affect the flag. 

HANDSHAKE OUTPUT MODE: 

The CB2 line will be set low on a write to PORT B. It will be reset high 
again when there is an active transition on the CB1 line. 

PULSE OUTPUT MODE: 

The CB2 line is set low for one cycle after a write to PORT B. 



DESCRIPTION 

Interrupt Input Mode 
Independent Interrupt Input Mode 
Input Mode 

Independent Input Mode 
Handshake Output Mode 
Pulse Output Mode 

Manual Output Mode (CB2 is held LOW) 
Manual Output Mode (CB2 is held HIGH) 



APPENDIX I 



315 



MANUAL OUTPUT MODE: 

The CB2 line is lield low. 

MANUAL OUTPUT MODE: 

The CB2 line is held high. 

R: CB1 CONTROL 

This bit selects the active transition of the input signal applied to the CB1 
pin. If this bit is 0, the CB1 interrupt flag will be set on a negative transition 
(high-to-low). If this bit is a 1 , the CB 1 interrupt flag will be set on a positive 
(low-to-high) transition. 

S:CA2 CONTROL 



s 


s 


s 




3 


2 


1 


DESCRIPTION 











Interrupt Input Mode 








1 


Independent Interrupt Input Mode 





1 





Input Mode 





1 


1 


Independent Input Mode 


1 








Handshake Output Mode 


1 





1 


Pulse Output Mode 


1 


1 





Manual Output Mode (CA2 is held LOW) 


1 


1 


1 


Manual Output Mode (GA2 is held HIGH) 



INTERRUPT INPUT MODE: 

The CA2 interrupt flag (IFR bit 0) will be set on a negative (high-to-low) 
transition on the CA2 input line. The CA2 interrupt bit will be cleared on 
a read or write to PORT A. 



INDEPENDENT INTERRUPT INPUT MODE: 

As above, the CA2 interrupt flag will be set on a negative transition on 
the CA2 input line. However, reading or writing to PORT A does not clear 
the flag. 

INPUT MODE: 

The CA2 interrupt flag (IFR bit 0) will be set on a positive (low-to-high) 
transition of the CA2 line. The GA2 flag will be cleared on a read or write 
of PORT A. 



376 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



INDEPENDENT INPUT MODE: 

As above, the CA2 interrupt flag will be set on a positive transition on tlie 
CA2 line. However, reading or writing PORT A does not affect the flag. 

HANDSHAKE OUTPUT MODE: 

The CA2 line will be set low on a read or write to PORT A. it will be reset 
high again when there is an active transition on the CA1 line. 

PULSE OUTPUT MODE: 

The CA2 line is set low for one cycle after a read or write to PORT A. 

MANUAL OUTPUT MODE: 

The CA2 line is held low. 

MANUAL OUTPUT MODE: 

The CA2 line is held high. 

T: CA1 CONTROL 

This bit of the PGR selects the active transition of the Input signal applied 
to the CA1 input pin. If this bit is 0, the CA1 interrupt flag (Bit) will be set 
by a negative transition (high-to-low) on the CA1 pin. If this bit is 1 , the 
CA1 interrupt flag will be set by a positive transition (low-to-high). 

There are two registers associated with interrupts: The INTERRUPT FLAG 
REGISTER (IFR) and the INTERRUPT ENABLE REGISTER (lER). The 
IFR has eight bits, each one connected to a register in the 6522. Each bit 
in the IFR has an associated bit in the lER. The flag is set when a register 
wants to interrupt. However, no interrupt will take place unless the cor- 
responding bit in the lER is set. 

UVWXYZab: INTERRUPT FLAG REGISTER 

When the flag is set, the pin associated with that flag is attempting to 
interrupt the 6502. Bit U is not a normal flag. It goes high if both the flag 
and the corresponding bit in the INTERRUPT ENABLE REGISTER are 
set. It can be cleared only by clearing all the flags in the IFR or disabling 
all active interrupts in the lER. 



APPENDIX I 



317 



SET BY 

IRQ STATUS 
TIMER 1 time-out 



CLEARED BY 



U 
V 



Reading TIMER 1 low order 
counter and writing TIMER 1 
high order latch 



W 



TIMER 2 time-out 



Reading TIMER 2 low order 
counter and writing TIMER 2 
high order counter 



X 
Y 
Z 



CB1 pin active transition 
CB2 pin active transition 
Completion of 8 shifts 



Reading or writing PORT B 
Reading or writing PORT B 
Reading or writing the shift 
register 



a 



b 



CA1 pin active transition 



CA2 pin active transition 



Reading or writing PORT A 
(BBBBBBBB in above chart) 
Reading or writing PORT A 
(BBBBBBBB in above chart) 



cdefghij: INTERRUPT ENABLE REGISTER 
c: ENABLE CONTROL 

If this bit is a during a write to this register, each 1 in bits 0-6 clears the 

corresponding bit in the lER. If this bit is a 1 during this register, each 1 

in bits 0-6 will set the corresponding lER bit. 

d TIMER 1 time-out enable 

e TIMER 2 time-out enable 

f CB1 Interrupt enable 

g CB2 interrupt enable 

h Shift Interrupt enable 

i CA1 Interrupt enable 

j CA2 Interrupt enable 

PORTA 

This is similar to BBBBBBBB, except that the handshaking lines (CA1 and 
CA2) are unaffected by operations on this port. 



378 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



6526 (CIA) Complex Interface Adaptor 



REGISTER MAP 



RS3 


RS2 


RSI 


RSO 


REG 


NAME 



















PRA 


PERIPHERAL DATA REG A 











1 


1 


PRB 


PERIPHERAL DATA REG B 








1 





2 


DDRA 


DATA DIRECTION REG A 








1 


1 


3 


DDRB 


DATA DIRECTION REG B 





1 








4 


TALO 


TIMER A LOW REGISTER 





1 





1 


5 


TA HI 


TIMER A HIGH REGISTER 





1 


1 





6 


TB LO 


TIMER B LOW REGISTER 





1 


1 


1 


7 


TB HI 


TIMER B HIGH REGISTER 













8 


TOD lOths 


10ths OF SECONDS REGISTER 










1 


9 


TOD SEC 


SECONDS REGISTER 







1 





A 


TOD MIN 


MINUTES REGISTER 







1 


1 


B 


TOD HR 


HOURS— AM/PM REGISTER 




1 








C 


SDR 


SERIAL DATA REGISTER 




1 





1 


D 


ICR 


INTERRUPT CONTROL REGIS- 
TER 




1 


1 





E 


CRA 


CONTROL REG A 




1 


1 


1 


F 


CRB 


CONTROL REG B 



I/O Ports (PRA, PRB, DDRA, DDRB) 

Ports A and B each consist of an 8-bit Peripheral Data Register (PR) and 
an 8-bit Data Direction Register (DDR). If a bit in the DDR is set to a one, 
the corresponding bit in the PR is an output; if a DDR bit is set to a zero, 
the corresponding PR bit is defined as an input. On a READ, the PR 
reflects the information present on the actual port pins (PA0-PA7, PBO- 
PB7) for both input and output bits. Port A and Port B have passive pull- 
up devices as well as active pull-ups, providing both CMOS and TTL 
compatibility. Both ports have two TTL load drive capability. In addition to 
normal I/O operation, PB6 and PB7 also provide timer output functions. 

Handshaking 

Handshakin g on d ata transfers can be accomplished using the PC output 
pin and the FLAG input pin. PC will go low for one cycle following a read 
or write of PORT B. This signal can be used to indicate "data ready" at 
PORT B or "data accepted" from PORT B. Handshaking on 1 6-bit data 
transfers (using both PORT A and PORT B) is possible by always reading 



APPENDIX I 



319 



or writing PORT A first. FLAG is a negative edge sensitive input wiiich 
can be used for receiving Vne PC output from anot her 652 6, or as a g eneral 
purpose interrupt input. Any negative transition of FLAG will set the FLAG 
interrupt bit. 



REG 


NAME 


D7 


Ds 


D5 


D4 


D3 


D2 


D, 


Do 





PRA 


PA7 


PAe 


PA5 


PA4 


PA3 


PAs 


PA, 


PAo 


1 


PRB 


PB7 


PBe 


PB5 


PB4 


PB3 


PB2 


PBi 


PBo 


2 


DDRA 


DPA7 


DPAe 


DPA5 


DPA4 


DPA3 


DPA2 


DPA, 


DPAo 


3 


DDRB 


DPB7 


DPBs 


DPB5 


DPB4 


DPB3 


DPB2 


DPB, 


DPBo 



Interval Timers (Timer A, Timer B) 

Each interval timer consists of a 1 6-bit read-only Timer Counter and a 1 6- 
bit write-only Timer Latch. Data written to the timer are latched in the Timer 
Latch, while data read from the timer are the present contents of the Time 
Counter. The timers can be used independently or linked for extended 
operations. The various timer modes allow generation of long time delays, 
variable width pulses, pulse trains and variable frequency waveforms. 
Utilizing the CNT input, the timers can count external pulses or measure 
frequency, pulse width and delay times of external signals. Each timer has 
an associated control register, providing independent control of the fol- 
lowing functions: 

Start/Stop 

A control bit allows the time to be started or stopped by the microprocessor 
at any time. 

PB On/Off: 

A control bit allows the timer output to appear on a PORT B output line 
(PB6 for TIMER A and PB7 for TIMER B). This function overrides the 
DDRB control bit and forces the appropriate PB line to an output. 

Toggle/Pulse 

A control bit selects the output applied to PORT B. On every timer un- 
derflow the output can either toggle or generate a single positive pulse of 
one cycle duration. The Toggl e output is set high whenever the timer is 
started and is set low by RES. 



320 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



One-Shot/Continuous 

A control bit selects either tinner mode. In one-shot mode, the timer will 
count down from the latched value to zero, generate an interrupt, reload 
the latched value, then stop. In continuous mode, the timer will count from 
the latched value to zero, generate an interrupt, reload the latched value 
and repeat the procedure continuously. 

Force Load 

A strobe bit allows the timer latch to be loaded into the timer counter at 
any time, whether the timer is running or not. 

Input Mode: 

Control bits allow selection of the clock used to decrement the timer. 
TIMER A can count ^2 clock pulses or external pulses applied to the CNT 
pin. TIMER B can count <^2 pulses, external CNT pulses, TIMER A un- 
derflow pulses or TIMER A underflow pulses while the CNT pin is held 
high. 

The timer latch is loaded into the timer on any timer underflow, on a force 
load or following a write to the high byte of the prescaler while the timer 
is stopped. If the timer is running, a write to the high byte will load the 
timer latch, but not reload the counter. 



READ (TIMER) 
REG NAME 



4 


TALO 


TAL7 


TALs 


TALs 


TAU 


TAL3 


TAL2 


TAL, 


TALo 


5 


TA HI 


TAH7 


TAHe 


TAH5 


TAH4 


TAH3 


TAHs 


TAH, 


TAHo 


6 


TB LO 


TBL7 


TBLe 


TBU 


TBL4 


TBL3 


TBL2 


TBLi 


TBLo 


7 


TB HI 


TBH7 


TBHe 


TBHs 


TBH4 


TBH3 


TBH2 


TBH, 


TBHo 



WRITE (PRESCALER) 

REG NAME 



4 


TALO 


PAL7 


PALe 


PAL5 


PAL4 


PAL3 


PALs 


PAL, 


PALo 


5 


TA HI 


PAH7 


PAHe 


PAH5 


PAH4 


PAH3 


PAH2 


PAH, 


PAHo 


6 


TB LO 


PB7 


PBb 


PB5 


PB4 


PB3 


PB2 


PB, 


PBo 


7 


TB HI 


PBH7 


PBHs 


PBH5 


PBH4 


PBH3 


PBHa 


PBH, 


PBHo 



APPENDIX I 



321 



Time of Day Clock (TOD) 

The TOD clock is a special purpose timer for real-time applications. TOD 
consists of a 24-hour (AM/PM) clock with 1/1 0th second resolution, it is 
organized into 4 registers: 10ths of seconds, Seconds, IVlinutes and Hours. 
The AM/PM flag is in the MSB of the Hours register for easy bit testing. 
Each register reads out in BCD format to simplify conversion for driving 
displays, etc. The clock requires an external 60 Hz or 50 Hz (programm- 
able) TTL level input on the TOD pin for accurate timekeeping. In addition 
to time-keeping, a programmable ALARM is provided for generating an 
interrupt at a desired time. The ALARM registers are located at the same 
addresses as the corresponding TOD registers. Access to the ALARM is 
governed by a Control Register bit. The ALARM is write-only; any read of 
a TOD address will read time regardless of the state of the ALARM access 
bit. 

A specific sequence of events must be followed for proper setting and 
reading of TOD. TOD is automatically stopped whenever a write to the 
Hours register occurs. The clock will not start again until after a write to 
the lOths of seconds register. This assures TOD will always start at the 
desired time. Since a carry from one stage to the next can occur at any 
time with respect to a read operation, a latching function is included to 
keep all Time Of Day information constant during a read sequence. All 
four TOD registers latch on a read of Hours and remain latched until after 
a read of 1 0ths of seconds. The TOD clock continues to count when the 
output registers are latched. If only one register is to be read, there is no 
carry problem and the register can be read "on the fly," provided that any 
read of Hours is followed by a read of lOths of seconds to disable the 
latching. 



READ 



REG NAME 



8 


TOD 
10THS 














Ts 


T4 


T2 


T, 


9 


TOD 
SEC 





SH4 


SHa 


SH, 


SLs 


SL4 


SL2 


SL, 


A 


TOD 
MIN 





MH4 


MHa 


MH, 


MLg 


ML4 


ML2 


ML, 


B 


TOD HR 


PM 








HH 


HLa 


HU 


HL2 


HL, 



322 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



WRITE 

CRB7 = TOD 

CRB7 = 1 ALARM 

(SAME FORMAT AS READ) 

Serial Port (SDR) 

The serial port is a buffered, 8-bit synchronous shift register system. A 
control bit selects input or output mode. In input mode, data on the SP 
pin is shifted into the shift register on the rising edge of the signal applied 
to the CNT pin. After 8 CNT pulses, the data in the shift register is dumped 
into the Serial Data Register and an interrupt is generated. In the output 
mode, TIMER A is used for the baud rate generator. Data is shifted out 
on the SP pin at V2 the underflow rate of TIMER A. The maximum baud 
rate possible is <f>2 divided by 4, but the maximum useable baud rate will 
be determined by line loading and the speed at which the receiver responds 
to input data. Transmission will start following a write to the Serial Data 
Register (provided TIMER A is running and in continuous mode). The 
clock signal derived from TIMER A appears as an output on the CNT pin. 
The data in the Serial Data Register will be loaded into the shift register 
then shift out to the SP pin when a CNT pulse occurs. Data shifted out 
becomes valid on the falling edge of CNT and remains valid until the next 
falling edge. After 8 CNT pulses, an interrupt is generated to indicate more 
data can be sent. If the Serial Data Register was loaded with new infor- 
mation prior to this interrupt, the new data will automatically be loaded 
into the shift register and transmission will continue. If the microprocessor 
stays one byte ahead of the shift register, transmission will be continuous. 
If no further data is to be transmitted, after the 8th CNT pulse, CNT will 
return high and SP will remain at the level of the last data bit transmitted. 
SDR data is shifted out MSB first and serial input data should also appear 
in this format. 

The bidirectional capability of the Serial Port and CNT clock allows many 
6526 devices to be connected to a common serial communication bus on 
which one 6526 acts as a master, sourcing data and shift clock, while all 
other 6526 chips act as slaves. Both CNT and SP outputs are open drain 
to allow such a common bus. Protocol for master/slave selection can be 
transmitted over the serial bus, or via dedicated handshaking lines. 



REG NAME 





SDR 


s. 




S5 




S3 


S2 


s, 


So 



APPENDIX I 



323 



Interrupt Control (ICR) 

There are five sources of interrupts on the 6526: underflow from TIMER 
A, und erflow from TIMER B, TOD ALARM, Serial Port full/empty and 
FLAG. A single register provides masking and interrupt information. The 
interrupt Control Register consists of a write-only MASK register and a 
read-only DATA register. Any interrupt will set the corresponding bit in the 
DATA register. Any interrupt which is enabled by the MASK register will 
set the IR bit (MSB) of the DATA register and bring the IRQ pin low. In a 
multi-chip system, the IR bit can be polled to detect which chip has gen- 
erated an interrupt request. The interrupt DATA register is cleared and 
the IRQ line returns high following a read of the DATA register. Since each 
interrupt sets an interrupt bit regardless of the MASK, and each interrupt 
bit can be selectively masked to prevent the generation of a processor 
interrupt, it is possible to intermix polled interrupts with true interrupts. 
However, polling the IR bit will cause the DATA register to clear, therefore, 
it is up to the user to preserve the information contained in the DATA 
register if any polled interrupts were present. 

The MASK register provides convenient contr ol of ind ividual mask bits. 
When writing to the MASK register, if bit 7 (SET/CLEAR) of the data written 
is a ZERO, any mask bit written with a one will be cleared, while those 
mask bits written with a zero will be unaffected. If bit 7 of the data written 
is a ONE, any mask bit written with a one will be set, while those mask 
bits written with a zero will be unaffected. In order for an interrupt flag to 
set IR and generate an Interrupt Request, the corresponding MASK bit 
must be set. 

READ (INT DATA) 



REG NAME 



D 


ICR 


IR 








FLG 


SP 


ALRM 


TB 


TA 


REG 


NAME 




WRITE (INT MASK) 








D 


ICR 


S/C 


X 


X 


FLG 


SP 


ALRM 


TB 


TA 



Control Registers 

There are two control registers in the 6526, CRA and CRB. CRA is as- 
sociated with TIMER A and ORB is associated with TIMER B. The register 
format is as follows: 



324 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



CRA: 

Bit Name Function 

START 1 = START TIMER A, = STOP TIMER A. This 

bit is automatically reset when underflow oc- 
curs during one-shot mode. 

1 PBON 1 = TIMER A output appears on PB6, = PB6 

normal operation. 

2 OUTMODE 1 = TOGGLE, = PULSE 

3 RUNMODE 1 = ONE-SHOT, = CONTINUOUS 

4 LOAD 1 = FORGE LOAD (this is STROBE input, there 

is no data storage, bit 4 will always read back 
a zero and writing a zero has no effect). 

5 INMODE 1 = TIMER A counts positive CNT transitions, 

= TIMER A counts <^2 pulses. 

6 SPMODE 1 = SERIAL PORT output (CNT sources shift 

clock), = SERIAL PORT input (external shift 
clock required). 

7 TODIN 1 =50 Hz clock required on TOD pin for ac- 

curate time, 0=60 Hz clock required on TOD 

pin for accurate time. 

(Bits CRB0-CRB4 are identical to CRA0-CRA4 
for TIMER B with the exception that bit 1 con- 
trols the output of TIMER B on PB7). 
5,6 INMODE Bits CRB5 and CRB6 select one of four input 

modes for TIMER B as: 
CRB6 CRB5 

TIMER B counts 4>2 

pulses. 

1 TIMER B counts positive 

CNT transitions. 
1, TIMER B counts TIMER 

A underflow pulses. 

1 1 TIMER B counts TIMER 

A underflow pulses while 
CNT is high. 

7 ALARM 1=writing to TOD registers sets ALARM, 

= writing to TOD registers sets TOD clock. 



APPENDIX I 



325 



REG 


NAME 


TOD SP 
IN MODE 


IN 

MODE 


LOAD 


RUN 
MODE 


OUT 
MODE 


PB ON 


START 


E 


CRA 


= 60Hz 


= INPUT 


= 42 


1= FORCE 


= CONT 


0= PULSE 


= PBeOFF 


= STOP 












LOAD 














1=50H2 


1= OUT- 


1=CNT 


(STROBE) 


1=0.S. 


1= TOGGLE 


1=PB6 0N 


1= START 








PUT 















REG 


NAME 


ALARM 


IN 


MODE 


LOAD 


RUN 
MODE 


OUT 
MODE 


PB ON 


START 


F 


CRB 


= TOD 

1 = 

ALARM 




1 
1 
) 


0=62 
1=CNT 

= TA 

1 = CNT-TA 


1 = FORCE 
LOAD 

(STROBE) 


0=CONT. 
1=0.S. 


0= PULSE 
1 = TOGGLE 


= PB7 0FF 
1=PB7 0N 


= STOP 
1= START 


1 



All unused register bits are unaffected by a write and are forced to zero 
on a read. 



COMMODORE SEMICONDUCTOR GROUP reserves the right to 
make changes to any products herein to improve reliability, function 
or design. COMMODORE SEMICONDUCTOR GRbUP does not 
assume any liability arising out of the application or use of any product 
or circuit described herein; neither does it convey any license under 
its patent rights nor the rights of others. 



6566/6567 (VIC-II) Chip Specifications 

The 6566/6567 are multi-purpose color video controller devices for use in 
both computer video terminals and video game applications. Both devices 
contain 47 control registers which are accessed via a standard 8-bit mi- 
croprocessor bus (65XX) and will access up to 16k of memory for display 
information. The various operating modes and options within each mode 
are described. 

Character Display Mode 

in the character display mode, the 6566/6567 fetches CHARACTER 
POINTERS from the VIDEO MATRIX area of memory and translates the 
pointers to character dot location addresses in the 2048 byte CHARACTER 
BASE area of memory. The video matrix is comprised of 1000 consecutive 
locations in memory which each contain an eight-bit character pointer. 
The location of the video matrix within memory is defined by VM13-VM10 
in register 24($18) which are used as the 4 MSB of the video matrix 



326 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



address. The lower order 1 bits are provided by an internal counter (VC3- 
VCO) which steps through the 1000 character locations. Note that the 
6566/6567 provides 14 address outputs; therefore, additional system hard- 
ware may be required for complete system memory decodes. 



CHARACTER POINTER ADDRESS 



A13 


A12 


A11 


A10 


A09 


AOS 


A07 


A06 


AOS 


A04 


A03 


A02 


A01 


AGO 


VM13 


VM12 


VM11 


VM10 


VC9 


VC8 


VC7 


VC6 


VC5 


VC4 


VC3 


VC2 


VC1 


VCO 



The eight-bit character pointer permits up to 256 different character def- 
initions to be available simultaneously. Each character is an 8x8 dot 
matrix stored in the character base as eight consecutive bytes. The location 
of the character base is defined by CB13-CB11 also in register 24 ($18) 
which are used for the 3 most significant bits (MSB) of the character base 
address. The 1 1 lower order addresses are formed by the 8-bit character 
pointer from the video matrix (D7-D0) which selects a particular character, 
and a 3-bit raster counter (RC2-RC0) which selects one of the eight char- 
acter bytes. The resulting characters are formatted as 25 rows of 40 
characters each. In addition to the 8-bit character pointer, a 4-bit COLOR 
NYBBLE is associated with each video matrix location (the video matrix 
memory must be 12 bits wide) which defines one of sixteen colors for 
each character. 



CHARACTER DATA ADDRESS 



A13 


A12 


A11 


A10 


A09 


AOS 


A07 


A06 


AOS 


A04 


AOS 


A02 


A01 


AOO 


CB13 


CB12 


CB11 


D7 


D6 


D5 


D4 


D3 


D2 


D1 


DO 


RC2 


RC1 


RCO 



Standard Character Mode (MCM = BMM = 
ECM = 0) 

In the standard character mode, the 8 sequential bytes from the character 
base are displayed directly on the 8 lines in each character region. A "0" 
bit causes the background #0 color (from register 33 ($21 )) to be displayed 
while the color selected by the color nybble (foreground) is displayed for 
a "1" bit (see Color Code Table). 



APPENDIX I 



327 





CHARACTER 




FUNCTION 


BIT 


COLOR DISPLAYED 


Background 





Background #0 color 






(register 33 ($21)) 


Foreground 


1 


Color selected by 4-bit color nybble 



Therefore, each character has a unique color determined by the 4-bit color 
nybble (1 of 16) and all characters share the common background color. 



Multi-Color Character Mode (MCM = 1, 
BMM = ECM = 0) 

Multi-color mode provides additional color flexibility allowing up to four 
colors within each character but with reduced resolution. The multi-color 
mode is selected by setting the MCM bit in register 22 ($16) to "1 ," which 
causes the dot data stored in the character base to be interpreted in a 
different manner. If the MSB of the color nybble is a "0," the character 
will be displayed as described in standard character mode, allowing the 
two modes to be inter-mixed (however, only the lower order 8 colors are 
available). When the MSB of the color nybble is a "1" (if MCM:MSB(CM) 
= 1 ) the character bits are interpreted in the multi-color mode: 



FUNCTION 


CHARACTER 
BIT PAIR 


COLOR DISPLAYED 


Background 


00 


Background #0 Color 






(register 33 ($21 )) 


Background 


01 


Background #1 Color 






(register 34 ($22)) 


Foreground 


10 


Background #2 Color 






(register 35 ($23)) 


Foreground 


11 


Color specified by 3 LSB of color 






nybble 



Since two bits are required to specify one dot color, the character is now 
displayed as a 4 x 8 matrix with each dot twice the horizontal size as in 
standard mode. Note, however, that each character region can now con- 
tain 4 different colors, two as foreground and two as background (see 
MOB priority). 



328 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Extended Color Mode (ECM = 1, BMM = 
MCM = 0) 

The extended color mode allows the selection of Individual background 
colors for each character region with the normal 8x8 character resolution. 
This mode Is selected by setting the ECM bit of register 17 ($11) to "1." 
The character dot data Is displayed as in the standard mode (foreground 
color determined by the color nybble is displayed for a "1" data bit), but 
the 2 MSB of the character pointer are used to select the bacl<ground 
color for each character region as follows: 



CHAR. POINTER 




MS BIT PAIR 


BACKGROUND COLOR DISPLAYED FOR BIT 


00 


Background #0 color (register 33 ($21 )) 


01 


Background #1 color (register 34 ($22)) 


10 


Background #2 color (register 35 ($23)) 


11 


Background #3 color (register 36 ($24)) 



Since the two MSB of the character pointers are used for color information, 
only 64 different character definitions are available. The 6566/6567 will 
force CB10 and CB9 to "0" regardless of the original pointer values, so 
that only the first 64 character definitions will be accessed. With extended 
color mode each character has one of sixteen individually defined fore- 
ground colors and one of the four available background colors. 



NOTE: Extended color mode and multi-color mode should not be enabled simulta- 
neously^ 



Bit Map Mode 

In bit map mode, the 6566/6567 fetches data from memory in a different 
fashion, so that a one-to-one correspondence exists between each dis- 
played dot and a memory bit. The bit map mode provides a screen res- 
olution of 320H X 200V individually controlled display dots. Bit map mode 
is selected by setting the BMM bit in register 17 ($1 1) to a "1 ." The VIDEO 
MATRIX Is still accessed as In character mode, but the video matrix data 
is no longer Interpreted as character pointers, but rather as color data. 
The VIDEO MATRIX COUNTER is then also used as an address to fetch 
the dot data for display from the 8000-byte DISPLAY BASE. The display 
base address is formed as follows: 



APPENDIX I 



329 



A13 


A12 


All 


A10 


A09 


AOS 


A07 


A06 


AOS 


A04 


AOS 


A02 


A01 


AGO 


CB13 


VC9 


VC8 


VC7 


VC6 


VC5 


VC4 


VC3 


VC2 


VC1 


VCD 


RC2 


RC1 


RCO 



VCx denotes the video matrix counter outputs, RCx denotes tlie 3-bit raster 
line counter and CB13 is from register 24 ($18). Tlie video matrix counter 
steps tlirougli the same 40 locations for eight raster lines, continuing to 
the next 40 locations every eighth line, while the raster counter increments 
once for each horizontal video line (raster line). This addressing results 
in each eight sequential memory locations being formatted as an 8 x 8 
dot block on the video display. 

Standard Bit Map Mode (BMM = 1, 
MCM = 0) 

When standard bit map mode is in use, the color information is derived 
only from the data stored in the video matrix (the color nybble is disre- 
garded). The 8 bits are divided into two 4-bit nybbles which allow two 
colors to be independently selected in each 8 x 8 dot block. When a bit 
in the display memory is a "0" the color of the output dot is set by the 
least significant (lower) nybble (LSN). Similarly, a display memory bit of 
"1" selects the output color determined by the MSN (upper nybble). 



BIT 


DISPLAY COLOR 





Lower nybble of video matrix pointer 


1 


Upper nybble of video matrix pointer 



Multi-Color Bit Map Mode (BMM = MCM 

= V 

Multi-colored bit map mode is selected by setting the MCM bit in register 
22 ($16) to a "1" in conjunction with the BMM bit. Multi-color mode uses 
the same memory access sequences as standard bit map mode, but 
interprets the dot data as follows: 



BIT PAIR 


DISPLAY COLOR 


00 


Background #0 color (register 33 ($21 )) 


01 


Upper nybble of video matrix pointer 


10 


Lower nybble of video matrix pointer 


11 


Video matrix color nybble 



330 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Note that the color nybble (DB1 1 -DBS) IS used for the multi-color bit map 
mode, again, as two bits are used to select one dot color, the horizontal 
dot size is doubled, resulting in a screen resolution of 160H x 200V. 
Utilizing multi-color bit map mode, three independently selected colors can 
be displayed in each 8x8 block in addition to the background color. 

Movable Object Blocks 

The movable object block (MOB) is a special type of character which can 
be displayed at any one position on the screen without the block constraints 
inherent in character and bit map mode. Up to 8 unique MOBs can be 
displayed simultaneously, each defined by 63 bytes in memory which are 
displayed as a 24 x 21 dot array (shown below). A number of special 
features make MOBs especially suited for video graphics and game ap- 
plications. 



MOB DISPLAY BLOCK 



BYTE 


BYTE 


BYTE 


00 


01 


02 


03 


04 


05 


57 


58 


59 


60 


61 


62 



Enable 

Each MOB can be selectively enabled for display by setting its corre- 
sponding enable bit (MnE) to "1" in register 21 ($15). If the MnE bit is 
"0," no MOB operations will occur involving the disabled MOB. 

Position 

Each MOB is positioned via its X and Y position register (see register 
map) with a resolution of 512 horizontal and 256 vertical positions. The 
position of a MOB is determined by the upper-left corner of the array. X 
locations 23 to 347 ($17-$157) and Y locations 50 to 249 ($32-$F9) are 
visible. Since not all available MOB positions are entirely visible on the 
screen, MOBs may be moved smoothly on and off the display screen. 



APPENDIX I 



331 



Color 



Each MOB has a separate 4-bit register to determine the IVlOB color. The 
two MOB color modes are: 

STANDARD MOB (MnMC = 0) 

In the standard mode, a "0" bit of MOB data allows any background data 
to show through (transparent) and a "1 " bit is displayed as the MOB color 
determined by the corresponding MOB Color register. 

MULTI-COLOR MOB (MnMC = 1) 

Each MOB can be individually selected as a multi-color MOB via MnMC 
bits in the MOB Multi-color register 28 ($1C). When the MnMC bit is "1," 
the corresponding MOB is displayed in the multi-color mode. In the multi- 
color mode, the MOB data is interpreted in pairs (similar to the other multi- 
color modes) as follows: 



BIT PAIR 


COLOR DISPLAYED 


00 


Transparent 


01 


MOB Multi-color #0 (register 37 ($25)) 


10 


MOB Color (registers 39-46 ($27-$2E)) 


11 


MOB Multi-color #1 (register 38 ($26)) 



Since two bits of data are required for each color, the resolution of the 
MOB is reduced to 12x21, with each horizontal dot expanded to twice 
standard size so that the overall MOB size does not change. Note that up 
to 3 colors can be displayed in each MOB (in addition to transparent) but 
that two of the colors are shared among all the MOBs in the multi-color 
mode. 



Each MOB can be selectively expanded (2 x ) in both the horizontal and 
vertical directions. Two registers contain the control bits (MnXE,MnYE) 
for the magnification control: 



Magnification 



REGISTER 



FUNCTION 



23 ($17) 



Horizontal expand MnXE—"1" = expand; 

"0" = normal 

Vertical expand MnYE—"1"= expand; "0" = normal 



29 ($1D) 



332 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



When MOBs are expanded, no increase in resolution is realized. The same 
24x21 array (12x21 if multi-colored) is displayed, but the overall MOB 
dimension is doubled in the desired direction (the smallest MOB dot may 
be up to 4 X standard dot dimension if a MOB is both multi-colored and 
expanded). 

Priority 

The priority of each MOB may be individually controlled with respect to 
the other displayed information from character or bit map modes. The 
priority of each MOB is set by the corresponding bit (MnDP) of register 
27 ($1 B) as follows: 



REG BIT 


PRIORITY TO CHARACTER OR BIT MAP DATA 





Non-transparent MOB data will be displayed (MOB in 




front) 


1 


Non-transparent MOB data wil be displayed only in- 




stead of Bkgd #0 or multi-color bit pair 01 (MOB be- 




hind) 



MOB— DISPLAY DATA PRIORITY 



MnDP = 1 


MnDP = 


MOBn 

Foreground 

Background 


Foreground 

MOBn 

Background 



MOB data bits of "0" ("00" in multi-color mode) are transparent, always 
permitting any other information to be displayed. 

The MOBs have a fixed priority with respect to each other, with MOB 
having the highest priority and MOB 7 the lowest. When MOB data (except 
transparent data) of two MOBs are coincident, the data from the lower 
number MOB will be displayed. MOB vs. MOB data is prioritized before 
priority resolution with character or bit map data. 

Collision Detection 

Two types of MOB collision (coincidence) are detected, MOB to MOB 
collision and MOB to display data collision: 

1) A collision between two MOBs occurs when non-transparent output data of 
two MOBs are coincident. Coincidence of MOB transparent areas will not 
generate a collision. When a collision occurs, the MOB bits (MnM) in the 



APPENDIX I 



333 



MOB-MOB COLLISION register 30 ($1 E) will be set to "1 " for both colliding 
MOBs. As a collision between two (or more) MOBs occurs, the MOB-MOB 
collision bit for each collided MOB will be set. The collision bits remain set 
until a read of the collision register, when all bits are automatically cleared. 
MOBs collisions are detected even if positioned off-screen. 

2) The second type of collision is a MOB-DATA collision between a MOB and 
foreground display data from the character or bit map modes. The MOB- 
DATA COLLISION register 31 ($1 F) has a bit (MnD) for each MOB which 
is set to "1" when both the MOB and non-background display data are 
coincident. Again, the coincidence of only transparent data does not generate 
a collision. For special applications, the display data from the 0-1 multicolor 
bit pair also does not cause a collision. This feature permits their use as 
background display data without interfering with true MOB collisions. A MOB- 
DATA collision can occur off-screen in the horizontal direction if actual display 
data has been scrolled to an off-screen position (see scrolling). The MOB- 
DATA COLLISION register also automatically clears when read. 

The collision interrupt latches are set whenever the first bit of either register 
is set to "1 ." Once any collision bit within a register is set high, subsequent 
collisions will not set the interrupt latch until that collision register has been 
cleared to all "Os" by a read. 



MOB Memory Access 

The data for each MOB is stored in 63 consecutive bytes of memory. Each 
block of MOB data is defined by a MOB pointer, located at the end of the 
VIDEO MATRIX. Only 1000 bytes of the video matrix are used in the 
normal display modes, allowing the video matrix locations 1016-1 023 (VM 
base-i-$3F8 to VM base + $3FF) to be used for MOB pointers 0-7, re- 
spectively. The eight-bit MOB pointer from the video matrix together with 
the six bits from the MOB byte counter (to address 63 bytes) define the 
entire 14-bit address field: 



A13 


A12 


All 


A10 


A09 


AOS 


A07 


A06 


AOS 


A04 


A03 


A02 


A01 


AGO 


MP7 


MP6 


MPS 


MP4 


MP3 


MP2 


MP1 


MPO 


MCS 


MC4 


MCS 


MC2 


MCI 


MCO 



Where MPx are the MOB pointer bits from the video matrix and MCx are 
the internally generated MOB counter bits. The MOB pointers are read 
from the video matrix at the end of every raster line. When the Y position 
register of a MOB matches the current raster line count, the actual fetches 
of MOB data begin. Internal counters automatically step through the 63 
bytes of MOB data, displaying three bytes on each raster line. 



334 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Other Features 
Screen Blanking 

The display screen may be blanked by setting the DEN bit in register 1 7 
($11) to a "0." When the screen is blanked, the entire screen will be filled 
with the exterior color as in register 32 ($20). When blanking is active, 
only transparent (Phase 1) memory accesses are required, permitting full 
processor utilization of the system bus. MOB data, however, will be ac- 
cessed if the MOBs are not also disabled. The DEN bit must be set to "1 " 
for normal video display. 

Row/Column Select 

The normal display consists of 25 rows of 40 characters (or character 
regions) per row. For special display purposes, the display window may 
be reduced to 24 rows and 38 characters. There is no change in the format 
of the displayed information, except that characters (bits) adjacent to the 
exterior border area will now be covered by the border. The select bits 
operate as follows: 





NUMBER OF 




NUMBER OF 


RSEL 


ROWS 


CSEL 


COLUMNS 





24 rows 





38 columns 


1 


25 rows 


1 


40 columns 



The RSEL bit is in register 17 ($11) and the CSEL bit is in register 22 
($16). For standard display the larger display window is normally used, 
while the smaller display window is normally used In conjunction with 
scrolling. 



Scrolling 



The display data may be scrolled up to one entire character space in both 
the horizontal and vertical direction. When used in conjunction with the 
smaller display window (above), scrolling can be used to create a smooth 
panning motion of display data while updating the system memory only 
when a new character row (or column) is required. Scrolling is also used 
to center a fixed display within the display window. 



BITS 



X2,X1,X0 
Y2,Y1 ,Y0 



REGISTER 



22 ($16) 
17 ($11) 



FUNCTION 



Horizontal Position 
Vertical Position 



APPENDIX I 



335 



Light Pen 

The light pen input latches the current screen position into a pair of reg- 
isters (LPX.LPY) on a low-going edge. The X position register 19 ($13) 
will contain the 8 MSB of the X position at the time of transition. Since the 
X position is defined by a 512-state counter (9 bits) resolution to 2 hori- 
zontal dots is provided. Similarly, the Y position is latched to its register 
20 ($14) but here 8 bits provide single raster resolution within the visible 
display. The light pen latch may be triggered only once per frame, and 
subsequent triggers within the same frame will have no effect. Therefore, 
you must take several samples before turning the light pen to the screen 
(3 or more samples, average), depending upon the characteristics of your 
light pen. 

Raster Register 

The raster register is a dual-function register. A read of the raster register 
18 ($12) returns the lower 8 bits of the current raster position (the MSB- 
RC8 is located in register 1 7 ($1 1 )). The raster register can be interrogated 
to implement display changes outside the visible area to prevent display 
flicker. The visible display window is from raster 51 through raster 251 
($033-$0FB). A write to the raster bits (including RC8) is latched for use 
in an internal raster compare. When the current raster matches the written 
value, the raster interrupt latch is set. 

Interrupt Register 

The interrupt register shows the status of the four sources of interrupt. An 
interrupt latch in register 25 ($19) is set to "1" when an interrupt source 
has generated an interrupt request. The four sources of interrupt are: 



LATCH 


ENABLE 




BIT 


BIT 


WHEN SET 


IRST 


ERST 


Set when (raster count) = (stored raster 
count) 


IMDC 


EMDC 


Set by MOB-DATA collision register (first 
collision only) 


IMMC 


EMMC 


Set by MOB-MOB collision register (first 
collision only) 


ILP 


ELP 


Set by negative transition of LP input (once 
per frame) 


IRQ 




Set high by latch set and enabled (invert of 
IRQ/ output) 



336 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



To enable an interrupt request to set the IRQ/ output to "0," the corre- 
sponding interrupt enable bit in register 26 ($1 A) must be set to "1 ." Once 
an interrupt latch has been set, the latch may be cleared only by writing 
a "1" to the desired latch in the interrupt register. This feature allows 
selective handling of video interrupts without software required to "re- 
member" active interrupts. 

Dynamic Ram Refresh 

A dynamic ram refresh controller is built into the 6566/6567 devices. Five 
8-bit row addresses are refreshed every raster line. This rate guarantees 
a maximum delay of 2.02 ms between the refresh of any single row address 
in a 128 refresh scheme. (The maximum delay is 3.66 ms in a 256 address 
refresh scheme.) This refresh is totally transparent to the system, since 
the refresh occurs during Phase 1 of the system clock. The 6567 generates 
both RAS/ and CAS/ which are normally connected directly to the dynamic 
rams. RAS/ and CAS/ are generated for every Phase 2 and every video 
data access (including refresh) so that external clock generation is not 
required. 

Reset 

The reset bit (RES) in register 22 ($16) is not used for normal operation. 
Therefore it should be set to "0" when initializing the video chip. When 
set to a "1 ," the entire operation of the video chip is suspended, including 
video outputs and sync, memory refresh, and system bus access. 

Theory of Operation 

System Interface 

The 6566/6567 video controller devices interact with the system data bus 
in a special way. A 65XX system requires the system buses only during 
the Phase 2 (clock high) portion of the cycle. The 6566/6567 devices take 
advantage of this feature by normally accessing system memory during 
the Phase 1 (clock low) portion of the clock cycle. Therefore, operations 
such as character data fetches and memory refresh are totally transparent 
to the processor and do not reduce the processor throughput. The video 
chips provide the interface control signals required to maintain this bus 
sharing. 

The video devices provide the signal AEC (address enable control) which 
is used to disable the processor address bus drivers allowing the video 
device to access the address bus. AEC is active low which permits direct 



APPENDIX I 



337 



connection to the AEC input of the 65XX family. The AEC signal is normally 
activated during Phase 1 so that processor operation is not affected. Be- 
cause of this bus "sharing," all memory accesses must be completed in 
Vz cycle. Since the video chips provide a 1-MHz clock (which must be 
used as system Phase 2), a memory cycle is 500 ns including address 
setup, data access and, data setup to the reading device. 

Certain operations of the 6566/6567 require data at a faster rate than 
available by reading only during the Phase 1 time; specifically, the access 
of character pointers from the video matrix and the fetch of MOB data. 
Therefore, the processor must be disabled and the data accessed during 
the Phase 2 clock. This is accomplished via the BA (bus available) signal. 
The BA line is normally high but is brought low during Phase 1 to indicate 
that the video chip will require a Phase 2 data access. Three Phase-2 
times are allowed after BA low for the processor to complete any current 
memory accesses. On the fourth Phase 2 after BA low, the AEC signal 
will remain low during Phase 2 as the video chip fetches data. The BA 
line is normally connected to the RDY input of a 65XX processor. The 
character pointer fetches occur every eighth raster line during the display 
window and require 40 consecutive Phase 2 accesses to fetch the video 
matrix pointers. The MOB data fetches require 4 memory accesses as 
follows: 



PHASE 


DATA 


CONDITION 


1 


MOB Pointer 


Every raster 


2 


MOB Byte 1 


Each raster while MOB is displayed 


1 


MOB Byte 2 


Each raster while MOB is displayed 


2 


MOB Byte 3 


Each raster while MOB is displayed 



The MOB pointers are fetched every other Phase 1 at the end of each 
raster line. As required, the additional cycles are used for MOB data 
fetches. Again, all necessary bus control is provided by the 6566/6567 
devices. 



Memory Interface 

The two versions of the video interface chip, 6566 and 6567, differ in 
address output configurations. The 6566 has thirteen fully decoded ad- 
dresses for direct connection to the system address bus. The 6567 has 
multiplexed addresses for direct connection to 64K dynamic RAMs. The 
least significant address bits, A06-A00, are present on A06-A00 while RAS/ 
is brought low, while the most significant bits, A13-A08, are present on 
A05-A00 while CAS/ is brought low. The pins A11-A07 on the 6567 are 



338 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



z 
g 

H 
Q. 

E 
o 
w 
ui 
a 



o 
m 

Q 



m 

Q 



CM 

ID 
Q 



n 
m 
a 



ffi 

Q 



ffi 
Q 



(O 

m 
o 



1^ 
m 

Q 

(0 
(0 
UJ 

oc 

Q 
O 
< 



ccccccccccccccccg 

.2 .2 .2 .2 .2 .2 .2 .2 .2 .2 .2 .2 .2 .2 .2 .2 ~ 

■55 '55 '55 '55 'w 'w w '55 w w w 'w "w '« "w "m J5 m 
0000000000000000°*= 
a.a.a.a.Q.Q.a.Q.aLQ.Q.Q.Q.Q.Q.Q.9-(» 

x>x>-x>x>-x>-x>-x>-x>-x« 
ooT-T-cMCMcocorj-"<tu)U5totor«~r>-.'5 

OOOOOOOOOOOOOOOOW 



> - 



— X 

'o c c ffl 

£: 0} a> c 

L. a. a. UJ 

oc □ □ S 



2? o 

^ E S .'^ §■ 

ffl tc ^ O) t 

O g g 
S S £ m 



0000000000000000 
x>-x>x>x>-x>-x>-x>-x>- 
ooT--i-cjc\jcoco^'*inm<D<Dr^r>- 



00 o LU 

Xoox^-lJJO^ 

S CC _l _l S S 



I gg£ 



X?X>X>X>X>X>X>X>Sr,^X? 
ooi--i-cMCJcoco'sr-*tnintotor>-r>-i->-0£Q~'-X'^tIlS^S 



CO CM LLI CM O ^ 



CM 


CM 


CM 


CM 


CM 


CM 


CM 




CM 


CM 


CM 


CM 


CM 


CM 


CM 


CM 


CO 


X 


>- 


X 


>- 


X 


> 


X 




X 


> 


X 


>- 


X 


>- 


X 


>- 


X 










T— 


CM 


CM 


CO 


CO 


■t 




in 


10 


CO 


CO 




1^ 


CM 





































CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


00 


X 


>- 


X 


> 


X 


>- 


X 


>- 


X 


>- 


X 


>- 


X 


> 


X 


> 


X 












CM 


CM 


CO 


CO 


•<t 


'sr 


in 


in 


CO 


CO 






CO 




:s 


i 


i 
















IS 













_1 r^. (Y, -1 LU CO 

Luco5>:iuLU>-T-_ 

coOoIqIswscqci, 

a:£ri]i]2o5od 



UJ 











■t 
























00 


X 


> 


X 


? 


X 








X 


>- 


X 


> 


X 


>- 






X 












CM 


CM 


CO 


CO 






m 


in 


(O 


CO 






■si- 






i 


i 














m 















_^ in -St- 
7<X> 



UJ 



UJ O 

>- n 



S S S S Q OC 



^ ^ ^ I I 
SSS> I I 



in 


in 


in 


If) 


in 


in 


in 


in 


in 


in 


in 


10 


U1 


in 


in 


in 


00 


X 


>- 


X 


>- 


X 


> 


X 




X 


> 


X 


>- 


X 


>- 


X 


>- 


X 












CM 


CM 


CO 


CO 






m 


in 


CO 


CO 






in 






i 


i 














IS 


S 


S 


S 


S 







CO 


CO 


CO 


CO 


CO 


CO 


(O 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


00 


X 


> 


X 


>- 


X 


>- 


X 


> 


X 


> 


X 


>- 


X 


>- 


X 


>■ 


X 










i 


CM 


CM 


CO 


CO 






in 


in 


CO 


CO 






CO 


S 


S 


S 


s 




S 




s 


S 


S 


S 


S 






S 


S 



in 



CO 



CD in ,,, ty 

X >- UI CO >- r: 

^ £ in UJ w 2 

-I -I S QC S > 



I I 



1^ <D IM 

X >- 



UJ OC 



i I 



UJ CM 

11 



I I 













l>- 




1^ 


1^ 


1^ 


1^ 










1^ 


00 


X 


>- 


X 


> 


X 


> 


X 


>- 


X 


> 


X 


>- 


X 


>- 


X 


>- 


X 








i 




CM 


CM 


CO 


CO 






in 


in 


CO 


CO 


1^ 




r«. 


S 


s 


1 


s 


s 


S 


S 


s 


s 


S 


S 




S 


s 


S 


S 



CO l>* 

O O 

cc oc 



CO 1^ ,,, 

X >- LU 
Q. 0. N 
_i _i S 



UJ CO 

I s > £ 



OT-CMC0'SflO<0h~00O)<0QOQUJU.O'^CMC0'*in<OI^C0O)< 
OOOOOOOOOOOOOOOOi-'^i--i--i-i-i--i-i-i--'- 

Oi-CMco-st-incoh*ooo»o-i-CMco'*in<or«-ooo50t-cMco'^inco 

OOOOOOOOOOT--I--I-T-1-1-1--I-T-T-CMCMCMCMCMCMCM 



APPENDIX I 



339 



^ 0) 

< .9 

9 ^ 

m CO 
O O 



c 
g 

cc O 

S-m 
9 O 
>< 5 

CD CO 

O O 



c 
o 

'jm 

o 
O 

< 
O 

I 

CO 

O 



o i- 



o o o o 

o o o o 

O O OO 

O 1- CM CO 

-a T3 -a 

O) G) O) C7> 

^ ^ jk: ^ 

CO CO CQ CQ 



O 
IS 



o 


o 


o 


o 


o 


o 


o 


o 


o 


o 


o 


o 


o 


o 


o 


o 


O 


O 


O 


O 


O 


O 


O 


O 


o 




CM 


CO 




in 


(£> 


1^ 


CQ 


CO 


CQ 


CQ 


CQ 


CO 


CQ 


CO 


o 


o 


O 


O 


o 


O 


O 


O 












2 







CL O 

o o 



S Q 
o o 



0- O LU 

Q 5 X 



S Q 













Q. 


o 


LU 






Q 


IS 


x: 




Q 


CM 


CM 


CM 


CM 


CM 












Q. 


o 


LU 






O 




X 




Q 


CO 


CO 


CO 


CO 


CO 













o 
O 



o 


O 


O 


O 


O 


O 


T— 


CM 


CO 


CQ 


CQ 


CQ 



;r: o o o 

O O T- CM CO 



CM 



CO 



o 


o 


o 


o 


O 


o 


o 


o 


o 


i 


O 


O 


O 


O 


o 


O 


O 


O 




o 




CM 


CO 




in 


CO 


r«- 






i 


:e 


:s 






IS 






O 


o 


T— 

O 


o 


O 


O 


O 


O 


i 


o 




CM 


CO 


■>t 


in 


(O 






















CM 


CM 


CM 


CM 


CM 


CM 


CM 


CM 


CM 


i 


o 


O 


O 


o 


o 


o 


o 


o 




o 




CM 


CO 




in 


CO 








i 














CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


CO 


i 


o 


O 


O 


o 


O 


O 


O 


o 




o 




CM 


CO 


■<t 


in 


(O 








i 








IS 







Q. O LU 

Q 2 X S Q 

■<t ■<*■ 

;i s s IS s 



I I I I I I I I I I I I I I I 



as 
£ 

CO 



0. g LU ^ 

Q S X 2 Q 

in in in in in . 
S S S S S I 



0. 


O 


LU 






Q 




X 




Q 


CO 


(O 


(O 


CO 


(O 













I I I I I I I I I I I I I I 



I I 



I I I I I I I I I 



o 

(U 

c 
c 

8 



0. O UJ 

Q IS X S Q 

r>. rs. fs. r>. , 

s s s s s I 



I I I I I I I I I I I I I I 



COOQLULLO'.-CMCO'>i-LOCONOOC3)<CQOQLU 
■I-1-T-T-1-CMCMCMCMCMCMCVICMCMCMCMCMCMCMCM 

r r ^ »^ »^ » ^ >^ f t\ fn t f\ t f\ t f\ ff\ 

\TT try WT yy yy yy yy yy yy yy yy yy 

h-ooo)Oi-cMco^incDr^cooso-i-CMcO'*incD 

CMCMCMCOCOCOCOCOCOCOCOCOCO'd-^'*'*'*-*-* 



(0 

CO 
-D 

< 
lii 

H 

o 



340 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



COLOR CODES 



D4 


Do 


Ul 


UU 


ucv 


Hex* 






















BLACK 











1 


1 


1 


WHITE 








1 





2 


2 


RED 








1 


1 


3 


3 


CYAN 





1 








4 


4 


PURPLE 





1 





1 


5 


5 


GREEN 





1 


1 





6 


6 


BLUE 





1 


1 


1 


7 


7 


YELLOW 


1 











8 


8 


ORANGE 










1 


9 


9 


BROWN 







1 





A 


10 


LTRED 







1 


1 


B 


11 


DARK GRAY 




1 








C 


12 


MED GRAY 




1 





1 


D 


13 


LT GREEN 




1 


1 





E 


14 


LT BLUE 




1 


1 


1 


F 


15 


LT GRAY 



static address outputs to allow direct connection of these bits to a con- 
ventional 1 6K (2K X 8) ROM. (The lower order addresses require external 
latching.) 



6581 Sound Interface Device (SID) Chip 
Specifications 

Concept 

The 6581 Sound Interface Device (SID) is a single-chip, 3-voice electronic 
music synthesizer/sound effects generator compatible with the 65XX and 
similar microprocessor families. SID provides wide-range, high-resolution 
control of pitch (frequency), tone color (harmonic content), and dynamics 
(volume). Specialized control circuitry minimizes software overhead, fa- 
cilitating use in arcade/home video games and low-cost musical instru- 
ments. 

Features 

• 3 TONE OSCILLATORS 
Range: 0-4 kHz 



APPENDIX I 



341 



• 4 WAVEFORMS PER OSCILLATOR 

Triangle, Sawtooth, 
Variable Pulse, Noise 

• 3 AMPLITUDE MODULATORS 

Range: 48 dB 

• 3 ENVELOPE GENERATORS 

Exponential response 
Attack Rate: 2 ms— 8 s 
Decay Rate: 6 ms— 24 s 
Sustain Level: — peal< volume 
Release Rate: 6 ms — 24 s 

• OSCILLATOR SYNCHRONIZATION 

• RING MODULATION 

Description 

The 6581 consists of three synthesizer "voices" which can be used in- 
dependently or in conjunction with each other (or external audio sources) 
to create complex sounds. Each voice consists of a Tone Osciilator/Wave- 
form Generator, an Envelope Generator and an Amplitude Modulator. The 
Tone Oscillator controls the pitch of the voice over a wide range. The 
Oscillator produces four waveforms at the selected frequency, with the 
unique harmonic content of each waveform providing simple control of 
tone color. The volume dynamics of the oscillator are controlled by the 
Amplitude Modulator under the direction of the Envelope Generator. When 
triggered, the Envelope Generator creates an amplitude envelope with 
programmable rates of increasing and decreasing volume. In addition to 
the three voices, a programmable Filter is provided for generating complex, 
dynamic tone colors via subtractive synthesis. 

SIS allows the microprocessor to read the changing output of the third 
Oscillator and third Envelope Generator. These outputs can be used as 
a source of modulation information for creating vibrator, frequency/filter 
sweeps and similar effects. The third oscillator can also act as a random 
number generator for games. Two A/D converters are provided for inter- 
facing SID with potentiometers. These can be used for "paddles" in a 
game environment or as front panel controls in a music synthesizer. SID 
can process external audio signals, allowing multiple SID chips to be daisy- 
chained or mixed in complex polyphonic systems. 



342 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



SID Control Registers 

There are 29 eight-bit registers in SID which control the generation of 
sound. These registers are either WRITE-only or READ-only and are listed 
below in Table 1 . 

SID Register Description 

Voice 1 

FREQ LO/FREQ HI (Registers 00,01) 

Together these registers form a 1 6-bit number which linearly controls the 
frequency of Oscillator 1 . The frequency is determined by the following 
equation: 

Fout = (Fn X Fcik/1 677721 6) Hz 

Where Fn is the 1 6-bit number in the Frequency registers and Fdk is the 
system clock applied to the 4)2 input (pin 6). For a standard 1 .0-MHz clock, 
the frequency is given by: 

Fout = (Fn X 0.059604645) Hz 

A complete table of values for generating 8 octaves of the equally tempered 
musical scale with concert A (440 Hz) tuning is provided in Appendix E. 
It should be noted that the frequency resolution of SID is sufficient for any 
tuning scale and allows sweeping from note to note (portamento) with no 
discernable frequency steps. 

PW LO/PW HI (Registers 02,03) 

Together these registers form a 12-bit number (bits 4-7 of PW HI are not 
used) which linearly controls the Pulse Width (duty cycle) of the Pulse 
waveform on Oscillator 1 . The pulse width is determined by the following 
equation: 

PWout = (PWn/40.95)% 

Where PWn is the 12-bit number in the Pulse Width registers. 

The pulse width resolution allows the width to be smoothly swept with no 
discernable stepping. Note that the Pulse waveform on Oscillator 1 must 
be selected in order for the Pulse Width registers to have any audible 



APPENDIX I 



343 



>-.>.>-.>■. 



a £ 

EC P 



9 9 

C DC 



9 9 9 9 

" UJ ^ ^ 



b 

DC 



i 



9 

UJ 

t 

DC 



DC 

3 



DC 



9 9 



ii 



9 I 



11 ii I iili 



« 3 I „ 

I iiii 



il 



if 


if 


i 


t 


i 


f 


1 




if 


i 


i 


i 


i 




i£' 


■T 


i 


i 


ii 


i 


1 


tT 


if 


i 


i 




i 


i 




iT 


i 






1 


1 


iH! 


iF 


i 








i 


I? 




i 






1 


1 


it 


if 


t 


1 


1 


1 


1 



S 5 3 S S S S 

^OOOOi- '-i- 

4POOOOO oo 

^ooooo oo 



if 


if 


1 


t 


1 


i 


i 


iT 


if 




i 


i 




i 


if 


iT 


i 


i 


ii 


i 


i 


if 


if 


i 


i 


1 


f 


S 


I? 




i 




i 


f 


i 


if 


iF 


i 






i 


i 


if 


iT 


t 






f 


i 


it 


iT 


i 




1 


1 


i 



g S S g S 2 B 



if 


if 


1° 


i 


1 


i 


f 


uT 


if 


i 


i 


1 


f 


i 


if 


ir 




i 


ii 


f 




if 




i 


i 


1 


i 




if 


iT 


i 






f 


f 


if 


iT 


i 








i 


if 


if 


f 






f 


f 


iir 


if 


i 




1 


1 


f 



g ° - 5! 5 5 



o j: 5! n 



, « » j; o a g 



344 MACHINE LANGUAGE FOR COMMODORE MACHINES 



^ h ^ h 

z z z z 

9 9 9 9 

^ ^ ^ t 



h h t ^ 

z z z z 

9 9 9 9 

a a 6 Q 



^1 



O — U. LU 

-1 I ia Q 

o o ui Q 

ql a. cc s 



o 

Q 

z 





i 


RLT1 


3 
§ 


2 




RLT2 i 




s 




FILT3 1 


i? 
§ 


1 




RLTEX 1 


J? 
§ 


1 




Ui 
IE 


0. 

-1 


1 




CO 
lU 
IT 


m 


1 




CM 

m 
m 
tc 


0. 
X 


1 


o 

2 


JS 
m 

(E 


30R= 1 



6 *• O .0 

I 5 s § i 

' £ 0. a lu 



i 


0. 


§ 


S 


i 


i 


6 


lU 


i 


i 


d 




i 


i 


S 


iff 


■i 


i 


S 


liT 


i 


i 


6 


m 


)? 

0. 


i 


S 


to 
UI 


i 


i 


6 





in <D N CO 



a> < OD o 



o 1- o 



o o o «- 



n ol S3 S 



^ n ^ 



APPENDIX I 



345 



effect. A value of or 4095 ($FFF) in the Pulse Width registers will produce 
a constant DC output, while a value of 2048 ($800) will produce a square 
wave. 

CONTROL REGISTER (Register 04) 

This register contains eight control bits which select various options on 
Oscillator 1 . 

Gate (Bit 0): The GATE bit controls the Envelope Generator for Voice 1 . 
When this bit is set to a one, the Envelope Generator is Gated (triggered) 
and the ATTACK/DECAY/SUSTAIN cycle is initiated. When the bit is reset 
to a zero, the RELEASE cycle begins. The Envelope Generator controls 
the amplitude of Oscillator 1 appearing at the audio output, therefore, the 
GATE bit must be set (along with suitable envelope parameters) for the 
selected output of Oscillator 1 to be audible. A detailed discussion of the 
Envelope Generator can be found at the end of this Appendix. 

SYNC (Bit 1): The SYNC bit, when set to a one, synchronizes the fun- 
damental frequency of Oscillator 1 with the fundamental frequency of 
Oscillator 3, producing "Hard Sync" effects. 

Varying the frequency of Oscillator 1 with respect to Oscillator 3 produces 
a wide range of complex harmonic structures from Voice 1 at the frequency 
of Oscillator 3. In order for sync to occur, Oscillator 3 must be set to some 
frequency other than zero but preferably lower than the frequency of 
Oscillator 1 . No other parameters of Voice 3 have any effect on sync. 

RING MOD (Bit 2): The RING MOD bit, when set to a one, replaces the 
Triangle waveform output of Oscillator 1 with a "Ring Modulated" com- 
bination of Oscillators 1 and 3. Varying the frequency of Oscillator 1 with 
respect to Oscillator 3 produces a wide range of non-harmonic overtone 
structures for creating bell or gong sounds and for special effects. In order 
for ring modulation to be audible, the Triangle waveform of Oscillator 1 
must be selected and Oscillator 3 must be set to some frequency other 
than zero. No other parameters of Voice 3 have any effect on ring mod- 
ulation. 

TEST (Bit 3): The TEST bit, when set to a one, resets and locl<s Oscillator 1 
at zero until the TEST bit is cleared. The Noise waveform output of Oscillator 1 
is also reset and the Pulse waveform output is held at a DC level. Normally 
this bit is used for testing purposes, however, it can be used to synchronize 
Oscillator 1 to externa! events, allowing the generation of highly complex 
waveforms under real-time software control. 



346 MACHINE LANGUAGE FOR COMMODORE MACHINES 



(Bit 4): When set to a one, the Triangle waveform output of Oscillator 1 
is selected. The Triangle wavefornn is low in harmonics and has a mellow, 
flute-like quality. 

(Bit 5): When set to a one, the Pulse waveform output of Oscillator 1 is 
selected. The Sawtooth waveform is rich in even and odd harmonics and 
has a bright, brassy quality. 

(Bit 6): When set to a one, the Pulse waveform of Oscillator 1 is selected. 
The harmonic content of this waveform can be adjusted by the Pulse 
Width registers, producing tone qualities ranging from a bright, hollow 
square wave to a nasal, reedy pulse. Sweeping the pulse width in real- 
time produces a dynamic "phasing" effect which adds a sense of motion 
to the sound. Rapidly jumping between different pulse widths can produce 
interesting harmonic sequences. 

NOISE (Bit 7): When set to a one, the Noise output waveform of Oscillator 1 
is selected. This output is a random signal which changes at the frequency 
of Oscillator 1 . The sound quality can be varied from a low rumbling to 
hissing white noise via the Oscillator 1 Frequency registers. Noise is useful 
in creating explosions, gunshots, jet engines, wind, surf and other un- 
pitched sounds, as well as snare drums and cymbals. Sweeping the os- 
cillator frequency with Noise selected produces a dramatic rushing effect. 

One of the output waveforms must be selected for Oscillator 1 to be au- 
dible, however, it is NOT necessary to de-select waveforms to silence the 
output of Voice 1 . The amplitude of Voice 1 at the final output is a function 
of the Envelope Generator only. 

NOTE: The oscillator output waveforms are NOT additive. If more 
than one output waveform is selected simultaneously, the result will 
be a logical ANDing of the waveforms. Although this technique can 
be used to generate additional waveforms beyond the four listed 
above, it must be used with care. If any other waveform is selected 
while Noise is on, the Noise output can "lock up." If this occurs, the 
Noise output will remain silent until reset by the TEST bit or by 
bringing RES (pin 5) low. 



ATTACK/DECAY (Register 05) 

Bits 4-7 of this register (ATK0-ATK3) select 1 of 16 ATTACK rates for 
the Voice 1 Envelope Generator. The ATTACK rate determines how rapidly 
the output of Voice 1 rises from zero to peak amplitude when the Envelope 
Generator is Gated. The 16 ATTACK rates are listed in Table 2. 



APPENDIX I 



347 



Bits 0-3 (DCYO— DCY3) select 1 of 16 DECAY rates for the Envelope 
Generator. The DECAY cycle follows the ATTACK cycle and the DECAY 
rate determines how rapidly the output falls from the peak amplitude to 
the selected SUSTAIN level. The 16 DECAY rates are listed in Table 2. 

SUSTAIN/RELEASE (Register 06) 

Bits 4-7 of this register (STNO— STN3) select 1 of 16 SUSTAIN levels 
for the Envelope Generator. The SUSTAIN cycle follows the DECAY cycle 
and the output of Voice 1 will remain at the selected SUSTAIN amplitude 
as long as the Gate bit remains set. The SUSTAIN levels range from zero 



Table 2. Envelope Rates 



VALUE 


ATTACK RATE 


DECAY/RELEASE 






RATE 


DEC (HEX) 


(Time/Cycle) 


(Time/Cycle) 


(0) 


2 ms 


6 ms 


1 (1) 


8 ms 


24 ms 


2 (2) 


16 ms 


48 ms 


3 (3) 


24 ms 


72 ms 


4 (4) 


38 ms 


114 ms 


5 (5) 


56 ms 


168 ms 


6 (6) 


68 ms 


204 ms 


7 (7) 


80 ms 


240 ms 


8 (8) 


100 ms 


300 ms 


9 (9) 


250 ms 


750 ms 


10 (A) 


500 ms 


1.5 s 


11 (B) 


800 ms 


2.4 s 


12 (C) 


1 s 


3s 


13 (D) 


3 s 


9s 


14 (E) 


5s 


15s 


15 (F) 


8s 


24 s 



NOTE: Envelope rates are based on a 1 .0-MHz <t)2 clock. For other 
4)2 frequencies, multiply the given rate by 1 MHz/<})2. The rates refer 
to the amount of time per cycle. For example, given an ATTACK 
value of 2, the ATTACK cycle would take 16 ms to rise from zero to 
peak amplitude. The DECAY/RELEASE rates refer to the amount of 
time these cycles would take to fall from peak amplitude to zero. 



348 MACHINE LANGUAGE FOR COMMODORE MACHINES 



to peak amplitude in 16 linear steps, with a SUSTAIN value of selecting 
zero amplitude and a SUSTAIN value of 15 ($F) selecting the peak am- 
plitude. A SUSTAIN value of 8 would cause Voice 1 to SUSTAIN at an 
amplitude one-half the peak amplitude reached by the ATTACK cycle. 

Bits 0-3 (RLS0-RLS3) select 1 of 16 RELEASE rates for the Envelope 
Generator. The RELEASE cycle follows the SUSTAIN cycle when the 
Gate bit is reset to zero. At this time, the output of Voice 1 will fall from 
the SUSTAIN amplitude to zero amplitude at the selected RELEASE rate. 
The 16 RELEASE rates are identical to the DECAY rates. 

NOTE: The cycling of the Envelope Generator can be altered at any 
point via the Gate bit. The Envelope Generator can be Gated and 
Released without restriction. For example, if the Gate bit is reset 
before the envelope has finished the ATTACK cycle, the RELEASE 
cycle will immediately begin, starting from whatever amplitude had 
been reached. If the envelope is then gated again (before the RE- 
LEASE cycle has reached zero amplitude), another ATTACK cycle 
will begin, starting from whatever amplitude had been reached. This 
technique can be used to generate complex amplitude envelopes 
via real;time software control. 



Voice 2 

Registers 07-$0D control Voice 2 and are functionally identical to registers 
00-06 with these exceptions: 

1) When selected, SYNC synchronizes Oscillator 2 with Oscillator 1. 

2) When selected, RING MOD replaces the Triangle output of Oscillator 2 with 
the ring modulated combination of Oscillators 2 and 1 . 



Voice 3 

Registers $0E-$14 control Voice 3 and are functionally identical to reg- 
isters 00-06 with these exceptions: 

1) When selected, SYNC synchronizes Oscillator 3 with Oscillator 2. 

2) When selected, RING MOD replaces the Triangle output of Oscillator 3 with 
the ring modulated combination of Oscillators 3 and 2. 

Typical operation of a voice consists of selecting the desired parameters: 
frequency, waveform, effects (SYNC, RING MOD) and envelope rates, 
then gating the voice whenever the sound is desired. The sound can be 
sustained for any length of time and terminated by clearing the Gate bit. 



APPENDIX I 



349 



Each voice can be used separately, with independent parameters and 
gating, or in unison to create a single, powerful voice. When used in unison, 
a slight detuning of each oscillator or tuning to musical intervals creates 
a rich, animated sound. 

Filter 

FC LO/FC HI (Registers $15,$16) 

Together these registers form an 11 -bit number (bits 3-7 of FC LO are 
not used) which linearly controls the Cutoff (or Center) Frequency of the 
programmable Filter. The approximate Cutoff Frequency ranges from 30 
Hz to 12 KHz. 

RES/FILT (Register $17) 

Bits 4-7 of this register (RES0-RES3) control the resonance of the filter. 
Resonance is a peaking effect which emphasizes frequency components 
at the Cutoff Frequency of the Filter, causing a sharper sound. There are 
16 resonance settings ranging linearly from no resonance (0) to maximum 
resonance (15 or $F). Bits 0-3 determine which signals will be routed 
through the Filter: 

FiLT 1 (Bit 0): When set to a zero. Voice 1 appears directly at the audio 
output and the Filter has no effect on it. When set to a one, Voice 1 will 
be processed through the Filter and the harmonic content of Voice 1 will 
be altered according to the selected Filter parameters. 

FILT 2 (Bit 1): Same as bit for Voice 2. 

FILT 3 (Bit 2): Same as bit for Voice 3. 

FILTEX (Bit 3): Same as bit for External audio input (pin 26). 

MODE VOL (Register $18) 

Bits 4-7 of this register select various Filter mode and output options: 

LP (Bit 4): When set to a one, the Low-Pass output of the Filter is selected 
and sent to the audio output. For a given Filter input signal, all frequency 
components below the Filter Cutoff Frequency are passed unaltered, while 
all frequency components above the Cutoff are attenuated at a rate of 12 
dB/Octave. The Low-Pass mode produces full-bodied sounds. 

BP (Bit 5): Same as bit 4 for the Bandpass output. All frequency com- 
ponents above and below the Cutoff are attenuated at a rate of 6 dB/ 
Octave. The Bandpass mode produces thin, open sounds. 



350 MACHINE LANGUAGE FOR COMMODORE MACHINES 



HP (Bit 6): Same as bit 4 for tlie High-Pass output. All frequency com- 
ponents above tfie Cutoff are passed unaltered, wliile all frequency com- 
ponents below thie Cutoff are attenuated at a rate of 12 dB/Octave. The 
High-Pass mode produces tinny, buzzy sounds. 

3 OFF (Bit 7): When set to a one, the output of voice 3 is disconnected 
from the direct audio path. Setting Voice 3 to bypass the Filter (FILT 3 = 
0) and setting 3 OFF to a one prevents Voice 3 from reaching the audio 
output. This allows Voice 3 to be used for modulation purposes without 
any undesirable output. 

NOTE: The Filter output modes ARE additive and multiple Filter 
modes may be selected simultaneously. For example, both LP and 
HP modes can be selected to produce a Notch (or Band Reject) 
Filter response. In order for the Filter to have any audible effect, at 
least one Filter output must be selected and at least one Voice must 
be routed through the Filter. The Filter is, perhaps, the most important 
element in SID as it allows the generation of complex tone colors 
via subtractive synthesis (the Filter is used to eliminate specific fre- 
quency components from a harmonically rich input signal). The best 
results are achieved by varying the Cutoff Frequency in real-time. 



Bits 0-3 (VOL0-VOL3) select 1 of 16 overall Volume levels for the final 
composite audio output. The output volume levels range from no output 
(0) to maximum volume (15 or $F) in 16 linear steps. This control can be 
used as a static volume control for balancing levels in multi-chip systems 
or for creating dynamic volume effects, such as Tremolo. Some Volume 
level other than zero must be selected in order for SID to produce any 
sound. 



Miscellaneous 

POTX (Register $19) 

This register allows the microprocessor to read the position of the poten- 
tiometer tied to POTX (pin 24), with values ranging from at minimum 
resistance, to 255 ($FF) at maximum resistance. The value is always valid 
and is updated every 512 (1)2 clock cycles. See the Pin Description section 
for information on pot and capacitor values. 

POTY (Register $1A) 

Same as POTX for the pot tied to POTY (pin 23). 



APPENDIX I 



351 



OSC 3/RANDOM (Register $1B) 

This register allows the microprocessor to read the upper 8 output bits of 
Oscillator 3. The character of the numbers generated is directly related to 
the waveform selected. If the Sawtooth waveform of Oscillator 3 is se- 
lected, this register will present a series of numbers incrementing from 
to 255 ($FF) at a rate determined by the frequency of Oscillator 3. If the 
Triangle waveform is selected, the output will increment from up to 255, 
then decrement down to 0. If the Pulse waveform is selected, the output 
will jump between and 255. Selecting the Noise waveform will produce 
a series of random numbers, therefore, this register can be used as a 
random number generator for games. There are numerous timing and 
sequencing applications for the OSC 3 register, however, the chief function 
is probably that of a modulation generator. The numbers generated by 
this register can be added, via software, to the Oscillator or Filter Fre- 
quency registers or the Pulse Width registers in real-time. Many dynamic 
effects can be generated in this manner. Siren-like sounds can be created 
by adding the OSC 3 Sawtooth output to the frequency control of another 
oscillator. Synthesizer "Sample and Hold" effects can be produced by 
adding the OSC 3 Noise output to the Filter Frequency control registers. 
Vibrato can be produced by setting Oscillator 3 to a frequency around 
7 Hz and adding the OSC 3 Triangle output (with proper scaling) to the 
Frequency control of another oscillator. An unlimited range of effects are 
available by altering the frequency of Oscillator 3 and scaling the OSC 3 
output. Normally, when Oscillator 3 is used for modulation, the audio output 
of Voice 3 should be eliminated (3 OFF = 1). 

ENV 3 (Register $1C) 

Same as OSC 3, but this register allows the microprocessor to read the 
output of the Voice 3 Envelope Generator. This output can be added to 
the Filter Frequency to produce harmonic envelopes, WAH-WAH, and 
similar effects. "Phaser" sounds can be created by adding this output to 
the frequency control registers of an oscillator. The Voices Envelope 
Generator must be Gated in order to produce any output from this register. 
The OSC 3 register, however, always reflects the changing output of the 
oscillator and is not affected in any way by the Envelope Generator. 



352 MACHINE LANGUAGE FOR COMMODORE MACHINES 



6525 Tri-Port Interface 

Concept 



The 6525 TRI-PORT Interface (TPI) is designed to simplify the imple- 
mentation of complex I/O operations in microcomputer systems. It com- 
bines two dedicated 8-bit I/O ports with a third 8-bit port programmable 
for either normal I/O operations or priority interrupt/handshal<ing control. 
Depending on the mode selected, the 6525 can provide 24 individually 
programmable I/O lines or 16 I/O lines, 2 handshake lines and 5 priority 
interrupt inputs. 

6525 Addressing 

6525 REGISTERS/(Direct Addressing) 



*000 


RO 


PRA— Port Register A 


001 


R1 


PRB— Port Register B 


010 


R2 


PRC— Port Register C 


oil 


R3 


DDRA — Data Direction Register A 


100 


R4 


DDRB— Data Direction Register B 


101 


R5 


DDRC — Data Direction Register C/interrupt Mask Register 


110 


R6 


CR— Control Register 


111 


R7 


AIR — Active Interrupt Register 



•NOTE: RS2, RSI, RSO respectively 



6525 Control Registers 



CR 
AIR 
DDRC 

When MC = 1 
PRC 

When MC = 1 



CBi 


CBo 


CAi 


CAo 


IE4 


IE3 


IP 


MC 








A4 


A3 


A2 


Ai 


Ao 








M4 


M3 


Mg 


Mi 


Mo 


















CB 


CA 


IRQ 


I4 


I3 


I2 


I1 


■o 



CA, CB Functional Description 

The CA, CB lines are outputs used in the same fashion as the CA2 and 
CB2 output of the 6520. 



APPENDIX I 



353 



CA Output Modes 



CAi CAo 



MODE 



DESCRIPTION 



"Handshake" 
on Read 



Pulse Output 



Manual 
Output 

Manual 
Output 



CA is set high on an active transition of the I3 
interrupt input signal and set low by a micropro- 
cessor "Read A Data" operation. This allows 
positive control of data transfers from the pe- 
ripheral device to the microprocessor. 

CA goes low for IMS after a "Read A Data" op- 
eration. This pulse can be used to signal the 
peripheral device that data was taken. 

CA set low. 
CA set high. 



CB Output Modes 



CB-| CBq 



MODE 



DESCRIPTION 




1 



"Handshake" 
on Write 



Pulse Output 



Manual 
Output 

Manual 
Output 



CB is set low on microprocessor "Write B Data" 
operation and is set high by an active transition 
of the I4 interrupt input signal. This allows positive 
control of data transfers from the microprocessor 
to the peripheral device. 

CB goes low for IMS after a microprocessor "Write 
B Data" operation. This can be used to signal 
the peripheral device that data is available. 

CB set low. 
CB set high. 



INTERRUPT MASK REGISTER DESCRIPTION 

When the Interrupt Mode is selected (MC = 1), the Data Direction Register 
for Port C (DDRC) is used to enable or disable a corresponding interrupt 
input. For example: If Mq = then Iq is disabled and any Iq interrupt latched 
in the interrupt latch register will not be transferred to the AIR and will not 
cause IRQ to .go low. The interrupt latch can be cleared by writing a zero 
to the appropriate I bit in PRC. 



354 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



PORT REGISTER C DESCRIPTION 

Port Register C (PRC) can operate in two modes. Tiie mode is controlled 
by bit MC in register CR. When MC = 0, PRC is a standard I/O port, 
operating identically to PRA & PRB. If MC = 1 , then port register C is 
used for handshal<ing and priority interrupt input and output. 



PRC When MC = 0: 

z 



PC7 


PCs 


PCs 


PC4 


PC3 


PC2 


PCi 


PCo 


PRC When MC = 1: 


CB 


CA 


IRQ 


I4 


I3 


I2 


I1 


lo 



INTERRUPT EDGE CONTROL 

Bits IE4 and IE3 in the control register (CR) are used to determine the 
active edge which will be recognized by the interrupt latch. 

If IE4 (IE3) = then I4 (I3) latch will be set on a negative transition of I4 

(I3) input. 

If IE4 (IE3) = 1 then I4 (I3) latch will be set on a positive transition of the 
U (I3) input. 

All other interrupt latches (I2. 11, lo) are set on a negative transition of the 
corresponding interrupt input. 



I4 


I3 


I2 


I1 


_o 



Interrupt Latch Register 

Clears on Read of AIR Using Following 
Equation 

ILR ^ ILR @ AIR 



A4 


A3 


A2 


Ai 


Ao 



IP 



Active Interrupt Register 

Clears on Write to AIR 

Interrupt Priority Select 

IP = No Priority 



IP = 1 Interrupts Prioritized 



APPENDIX I 



355 



FUNCTIONAL DESCRIPTION 

1 . IP = No Priority 

All interrupt information latched into interrupt latch register (ILR) is im- 
mediately transferred into active interrupt register (AIR) and IRQ is pulled 
low. Upon read of interrupt the IRQ is reset high and the appropriate bit(s) 
of the interrupt latch register is cleared by exclusive OR-ing. The ILR with 
AIR (ILR0AIR). After the appropriate interrupt request has been serviced 
a Write to the AIR will clear it and initiate a new interrupt sequence if any 
interrupts were received during previous interrupt sen/icing. In this non- 
prioritized mode it is possible for two or more interrupts to occur simul- 
taneously and be transferred to the AIR. If this occurs it is a software effort 
to recognize this and act accordingly. 

2. IP = 1 Interrupts Prioritized 

In this mode the Interrupt Inputs are prioritized in the following order I4 > 

I3 > I2 > I1 > lo 

In this mode only one bit of the AIR can be set at any one time. If an 
interrupt occurs it is latched into the interrupt latch register, the IRQ line 
is pulled low and the appropriate bit of the AIR is set. To understand fully 
the operation of the priority interrupts it is easiest to consider the following 
examples. 

A. The first case is the simplest. A single interrupt occurs and the pro- 
cessor can service it completely before another interrupt request is 
received. 

1 . Interrupt 1 1 is received. 

2. Bit_li is set high in Interrupt Latch Register. 

3. IRQ is pulled low. 

4. Ai is set high. 

5. Processor recognizes IRQ and reads AIR to determine which in- 
terrupt occurred. 

6. Bit I1 is reset and IRQ is reset to high. 

7. Processor Services Interrupt and signals completion of Service 
routine by writing to AIR. 

8. Ai is reset low and interrupt sequence is complete. 

B. The second case occurs when an interrupt has been received and a 
higher priority interrupt occurs. (See Note) 

1 . Interrupt I1 is received. 

2. Bit I 1 is set high on the Interrupt Latch Register. 

3. IRQ is pulled low and Ai is set high. 



356 MACHINE LANGUAGE FOR COMMODORE MACHINES 



4. Processor recognizes IRQ and reads AIR to determine which 
interrupt occurred. 

5. Bit li is reset and IRQ is reset high. 

6. Processor begins servicing li interrupt and the I2 interrupt is re- 
ceived. 

7. A2 is set, Ai is reset low and IRQ is pulled low. 

8. Processor has not yet completed servicing I, interrupt so this 
routi ne w ill be automatically stacked in 6500 stack queue when 
new IRQ for I2 of interrupt is received. 

9. Processor reads AIR to determine I2 interrupt occurrence and bit 
I2 of interrupt latch is reset. 

10. Processor services I2 interrupt, clears A2 by writing AIR and re- 
turns from interrupt. Returning from interrupt causes 650X pro- 
cessor to resume servicing I1 interrupt. 

11. Upon clearing A2 bit in AIR, the A, bit will not be restored to a 
one. Internal circuitry will prevent a lower priority interrupt from 
interrupting the resumed I1. 

C. The third case occurs when an interrupt has been received and a 
lower priority interrupt occurs. 

1. Interrupt I, is received and latched. 

2. IRQ is pulled low and A-, is set high. 

3. Processor recognizes IRQ and reads AIR to determine that 1^ in- 
terrupt occurred. 

4. Processor logic servicing 1^ interrupt during which Iq interrupt oc- 
curs and is latched. 

5. Upon completion of I1 interrupt routine the processor writes AIR 
to clear A, to signal 6525 that interrupt servi ce is complete. 

6. Latch lo interrupt is transferred to AIR and IRQ is pulled low to 
begin new interrupt sequence. 



NOTE: It was indicated that the 6525 will maintain Priority Interrupt 
information from previously serviced interrupts. 

This is achieved by the use of an Interrupt Stack. This stack is pushed 
whenever a read of AIR occurs and is pulled whenever a write to 
AIR occurs. It is therefore important not to perform any extraneous 
reads or writes to AIR since this will cause extra and unwanted stack 
operations to occur. 

The only time a read of AIR should occur is to respond to an interrupt 
request. 

The only time a write of AIR should occur is to signal the 6525 that 
the interrupt service is complete. 



Disk User's 
Guide 

The optional disk holds programs supplementary to the book. The pro- 
grams are as follows: 

SUPEEMONl (for original ROM PET computers) 
SUPERMONE (for upgrade ROM PET/CBM computers) 
SUPERM0N4 (for 4.0 PET/CBIVI computers) 
SUPERMON . V (for VIC-20 computers) 
SOPERMONt^ (for Commodore 64 computers) 
SUPERMON INST(instructions, BASIC) 
SUPERMON + PET (for upgrade and 4.0 PET/CBM) 
SUPERMON + VIC (for VIC-20 computers) 
SUPERMON + fc<(for Commodore 64 computers) 
SUPERMON + INST (instructions, Basic) 
UNICOPYt^ (for Commodore 64) 
UNICOPY INST (instructions, BASIC) 
UNICOPY LIST (BASIC, all machines) 
]UNICOPY asSY (data file for UNICOPY LIST) 
COPY -ALL (for PET/CBM) 
COPY - &LL . I2A (for Commodore 64) 
CROSS REF (for PET/CBIVI) 
CROSS REF hA (for Commodore 64) 
CROSS REF 12fl (for Commodore 128) 
FACTORS (for PET/CBM) 

357 



358 MACHINE LANGUAGE FOR COMMODORE MACHINES 



FACTORS Vt< (for VIC-20, Commodore 64, and Plus-4) 
FACTORS 12fl (for Commodore 128) 
PENTOMINOS INST (instructions) 
PENTOMINOS (BASIC, all machines) 
PENTOMINOS PET (for PET/CBM) 

PENTOMINOS VLA (for VIC-20, Commodore 64, and Plus-4) 

PENTOMINOS lEfl (for Commodore 128) 

PENTOMINOS B15fl (boot for 8128 system) 

+ PENT01Sfl (program for 81 28) 

+ XFER (transfer sequence for 81 28) 

STRING THING (8ASIC, for PET/CBM) 

STRING THING 7hA (BASIC, for VIC-20, Commodore 64) 

STRING THING 15fl (for Commodore 128) 

ISAMPLE FILE (for use with STRING THING) 

These programs are public domain, and may be obtained from user groups. 
They are available here for user convenience. 

The following notes may be useful in using or studying the programs. 

SDPERMONl (for original ROM PET computers) 
SUPERMONS (for upgrade ROM PET/CBM computers) 
SOPERMON^ (for 4.0 PET/CBM computers) 
SUPERMON . V (for VIC-20 computers) 
SOPERMONt^ (for Commodore 64 computers) 
SUPERMON INST (instructions, BASIC) 

Supermen 2 and 4 are "extensions" to the built-in MLM of the respective 
machines. The other Supermon versions are complete monitors. These 
are the "original" Supermon programs. 

Remember that the programs on disk are "monitor generators," that is, 
they build the monitor for you. After the monitor has been built, you should 
remove the builder program so that you don't end up with two copies. In 
other words, after RON type .X to return to BASIC, NEW to scrap the 
builder, and then SYS^orSYSflto return to the monitor whenever de- 
sired. 

The monitor is always built near the top of memory. Its entry address can 
be determined by checking the TOM (top-of-memory) pointer. Monitors 
are complex, but feel free to ask the monitor to disassemble itself for your 
information. 

After Supermon is placed, you may load BASIC programs and use the 
computer normally. Supermon will remain until you shut off the power. 



APPENDIX d 



359 



SUPERMON + PET (for upgrade and 4.0 PET/CBM) 
SDPERMON + VIC (for VIC-20 computers) 
SliPERMON + (for Commodore 64 computers) 
SUPERMON + INST (instructions, Basic) 

A revised version of SDPERMON; tlie commands closely correspond to 
those of the built-in monitors of the Plus-4 and Commodore 128. Contains 
a number of convenience features not found in the original SUPER- 
MON. 

UNICOPYE,/; 

A utility for copying files from one disk to another, on a single drive; or 
copying from one disk to cassette tape. The program is written entirely in 
machine language, apart from the SYS that starts it up. 

Information is copied from the selected files into RAM memory. When the 
output phase begins, the data is then written to disk or tape. 

ONICOPY INST 

A BASIC program explaining how to use ONICOPYt^. 

UNICOPY LIST 
JUNICOPY ftSSY 

An assembly listing of program UNICOPY. Because UNICOPY is written 
entirely in machine language, a number of tasks are performed in the 
program that are often more conveniently done in BASIC. For example, 
files are opened and closed by machine language. This makes the program 
listing particularly interesting for students of these techniques. 

Assembly listings have a somewhat different appearance from the machine 
language programs this book has dealt with. The most visible difference 
is in the use of symbolic addresses. If there is any confusion, concentrate 
on the machine language half of the listing; that will clarify what's going 
on. Program UNICOPY LIST allows output to the screen or to a Com- 
modore printer. 

For cassette tape output, direct calls to the ROM routines are made; that's 
usually not good practice, but there's little choice here. 

The program is written in machine language so that the BASIC ROM can 
be flippped out, allowing for more memory space in which to copy pro- 
grams. 

COPY -ALL (for PET/CBM) 

COPY - ALL . I2A (for Commodore 64) 



360 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



A utility for copying files from one disk drive to another. You will find two 
SYS commands in the BASIC part of the program: one to get the directory, 
and the other to do the actual copying. 

Information is copied from the selected file into a BASIC string that has 
been set aside for the purpose. A similar technique may be found in the 
simpler STRING THING. 

CROSS REF (for PET/CBM) 
CROSS REF t< (for Commodore 64) 
CROSS REF lEfl (for Commodore 128) 

This program prepares a cross-reference listing for any selected BASIC 
program on disk. It cross-references both line numbers and variables. It's 
a good way to document a BASIC program. 

The program uses two table lookup techniques that may be confusing to 
the beginning machine language program reader. First, it classifies all 
characters received from BASIC in terms of "type "; this is done with a 
table of 256 elements, one for each possible character. Second, it uses 
a "state transition table" to record the nature of the job in progress; for 
example, after meeting a GOSUB "token," it will expect to receive a line 
number. 

The second SYS in the BASIC program is used to print the line numbers 
of the cross-reference. It employs an efficient binary-to-decimal conversion 
technique, which uses decimal mode. 

FaCTORS (for PET/CBM) 

FACTORS Vt< (for VIC-20, Commodore 64, and Plus-4) 
FfiCTORSiaa (for Commodore 128) 

This program finds factors of numbers up to nineteen digits long. This 
shows a powerful feature of machine language as opposed to BASIC: the 
size of numbers is not limited by the language. 

The program contains a number of useful techniques worth studying. First, 
it allows a decimal input of any number up to 19 digits (a 64-bit or 8-byte 
binary number). Second, to find factors it performs division with remainder. 
Finally, to print results, It must convert binary-to-decimal, using the same 
decimal mode technique as in CROSS REF. 

The program does not try all divisors. After trying a few initial values (2, 
3, and 5), it switches to a "30-counter" technique, trying only multiples of 
30 plus 1,7, 11, 17, 19,23, and 29. 

The machine language program Is relocated by BASIC so that it starts at 
hexadecimal (in the CI 28 version, IDDD) regardless of where it 



APPENDIX J 



361 



was originally loaded. This was originally done to allow for the VIC-20's 
variable start-of-BASIC, which rambles according to the amount of extra 
memory fitted. It turns out to be useful for study to have the program in a 
fixed location; so the PET/CI\^B version was also set up in this way. 

Students wishing to disassemble FACTORS will find the following infor- 
mation useful: 

vaRIABLES (see note for C-128): 

$034 R — number of times a factor divides evenly 

$□ 34 R— "equals" or "asterisk" character for formatting 

$U3AB — zero suppression flag 

$D3i^C— 30— counter 

$0350 to $0357— value under analysis 

$035fl to $035F— value work area 

$03bD to $03t7— "base" value for 30-counter 

$03fcC to $ 03 7 H— division work area, including: 

$D3EiC to $ 03 tF— remainder 

$0370 to $0377— quotient 

C-128 note: The above locations are sensitive in the C128; the above 
variables have been relocated to page B. Thus, instead of $034 R given 
above, address $OB<<=i will be used. 

PROGRAM (see note for C128): 

$13 00 : Main routine, including: 
$1300 : Start, clear work area 
$131D : Get number digits from user 
$1331 : Handle bad input 
$133 A : Begin factoring; check non-zero 
$1350 : Try divisors 2, 3, and 5 
$ 1 3 b 5 : Try higher divisors 
$13AE: Print remaining value. 
$ 1 3 B A : Prompt subroutine 
$13C4: Input and analyze digit 
$ 1 < B : Multiply-by-two subroutine 
$ 1 1 5 : Division subroutine 
$147 A : Try a divisor (short) 
$1<7D : Try a divisor (long) 
$1465: Check if remainder zero 
$ 1 4 5 : Log factor if found 
$14AE : Check if more to do 
$14B<=I: Print value subroutine 



362 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



$1<D0: Print factor subroutine 
$15D^ : Clear output area 
$150F : Convert to decimal and print 
$1535: Print a digit with zero suppression 
$15t5 : 30-count values: 1,7,11, etc. 

CI 28 note: Basic is located at quite a high address in this machine; the 
start address of the program has been moved up to $100 □ to allow for 
this. The above table is correct if the extra offset is allowed; thus $1^15 
above becomes $1E15 in the CI 28. 

Even at machine language speeds, this program can tal<e a long time to 
analyze large factors and prime numbers. The RDN/STOP key is active 
to allow the user to stop the run. 

PENTOMINOS INST (Instructions) 
PENTOMINOS (BASIC, all machines) 
PENTOMINOS PET (for PET/CBM) 

PENTOMINOS Vt^ (for VIC-20, Commodore 64, and Plus-4) 
PENTOMINOS lEfl (for Commodore 128) 
PENTOMINOS BlEfl (boot for B128 system) 
+ PENT015fl (program for B128) 
+ XFE R (transfer sequence for 81 28) 

This is a puzzle solving problem. Pieces are fitted into a selected rectan- 
gular shape "visibly"— In other words, they may be seen on the screen 
as they are tried. 

The machine language programs follow the logic of the BASIC program 
precisely. The "shape tables" have been rearranged for greater machine 
language convenience (each piece Is reached by indexing; the index range 
of to 255 dictates the piece being selected and Its rotation). 

The machine language program uses no indirect addressing and no sub- 
routines. That is not necessarily good practice; it is largely a result of 
writing the program logic to exactly match the BASIC program. 

This program makes use of tables, and is worth studying for that reason. 
It is also useful to examine the close relationship between the BASIC 
program and its machine language equivalent, especially starting at line 
2000 In BASIC. 

As with FACTORS, the machine language program is relocated by BASIC 
so that it starts at hexadecimal 15kD (with tables starting at $1EFA) 
regardless of where it was originally loaded. Again, this is necessary for 
the VIC-20 and proves to be convenient for study purposes on all ma- 
chines — except the B-128 version, where this relocation does not happen. 



APPENDIX J 



363 



Students wishing to disassemble PENTOMINOS will find the following 
information useful: 



VARIABLES (see C128 note): 

$DB3C— piece number, BASIC variable P 
$D33D to $D33E— variables W1 and W2, board size 
$D33F — P1, number of pieces placed 
$□340 to $D3AB—U{..) log of pieces placed 
$D3<C to $0357— T(..) rotation of piece 
$035fl to $D35C— X(..) location of piece 
$D35D to $D3bl— Y(..) location of piece 
$a3tEto$D37 □— tables to place a piece 
$037F to $ 03 qc— board "edge" table 
$D3RD to $D3Dfl— B(...) the board. 

C128 note: The above locations are sensitive in the C128; the above 
variables have been relocated to page B. Thus, instead of $D3bE given 
above, address $DBt5 will be used. 

PROGRAM (see C128 note): 

$15tD: Start, BASIC line 1070 
$1SAA: Clear screen, BASIC line 1120 
$ 1 5 A S : Clear variables, set up 
$15CC : Find space, BASIC line 2010 
SltOD : Get new piece, BASIC line 2030 
Sltnq : Try piece, BASIC line 2060 
$ltflt : Put piece in, BASIC line 2120 
$lbEQ : Print "Solution", BASIC line 2170 
$1701 : Undraw piece, BASIC line 2190 
$ 1 7 AB : Rotate piece, BASIC line 2260 
$17BC : Give up on piece, BASIC line 2280 
$17C1 : Look for new piece, BASIC line 2300 

CI 28 note: Basic is located at quite a high address in this machine; the 
start address of the program has been moved up to SlFtD to allow for 
this. The above table is correct if the extra offset Is allowed; thus $lbDD 
above becomes SEDDD in the C128. 

The B128 version does not align to the above addresses. It is written to 
illustrate the "boot" loading system needed for that computer. Programs 
whose names begin with a + symbol are loaded by the bootstrap program; 
do not try to load them directly. 



364 MACHINE LANGUAGE FOR COMMODORE MACHINES 



STRING THING (BASIC, for PET/CBM) 

STRING THING Vt< (BASIC, for VIC-20, Commodore 64, Plus-4) 
STRING THING lEfl (Commodore 128) 
ISAMPLE FILE 

A simple machine language program , POKEable directly from BASIC, to 
substitute for an INPUT# statement. 

INPaT# has several limitations that sometimes make it awkward for use 
with files: 

• No more than 80 characters may be read. 

• The comma or colon character will break up input. 

• Leading spaces will disappear. 

STRING THING reads everything up to the next RETURN or end of 
file. It is pure BASIC, but POKEs machine language into the cassette 
buffer area. It finds the first variable and uses it as an input buffer. 

The 128 machine language program is brief and makes good study ma- 
terial. Since the program is in bank but the variable table is in bank 1 , 
it is necessary to call special Kernal routine INDFET ( $FF7^ ) to get 
the information. Later, when the program wishes to place a character into 
the string (which also resides in bank 1), it must call special Kernal routine 
INDSTA ( $FF77 ) to get it there. The manner in which the calls are set 
up is instructive. 



Glossary 



The numbers in parentheses indicate the chapter in which the word or, 
phrase is first used. 

Absolute address: (5) An address that can indicate any location in 
memory. 

Accumulator: (3) The A register; the register used for arithmetic. 

Address bus: (1) A bus that signals which part of memory is wanted 
for the next memory operation. 

Address mode: (5) The manner in which an instruction reaches in- 
formation within memory. 

Address: (1) The identity of a specific location within memory. 

Algorithm: (1) A method or procedure to perform a computing tasl<. 

Arithmetic shift or rotate: (4) A shift or rotate that usually preserves 
the sign of a number. 

Assembler: (2) A program that assembles or changes source code 
into object code. 

Assembly: (1 ) The process of changing source code into object code. 

Assembly code: (1) Also called source code. A program written in a 
somewhat human-readable form. Must be translated ("assembled") before 
use. 



365 



366 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Assembly language: (1) The set of instructions, or language, in which 
a source program must be written before assembly. 

Binary: (1) Something that has two possible states; a number based 
on digits, each of which has two possible states. 

Bit: (1) A binary digit; the smallest element of information within a 
computer. 

Bootstrap: (6) A program that starts up another program. 
Breakpoint: (8) A location where the program will stop so as to allow 
checking for errors. 

Bug: (8) An error within a program. 

Bus: (1) A collection of wires connecting many devices together. 

Byte: (1) Eight bits of information grouped together; the normal mea- 
sure of computer storage. 

Calling point: (2) The program location from which a subroutine is 
called into play; the subroutine will return to the calling point when finished. 

Channel: (8) A path connecting the computer to one of its external 
devices. 

Comment: (8) A program element which does not cause the computer 
to do anything, used as advice to the human program reader. 

Commutative: (3) A mathematical operation that works both ways, 
e.g., 3 + 4 gives the same result as 4 + 3. 

Control bus: (1) A bus that signals timing and direction of data flow 
to the various connected devices. 

Data bus: (1) A bus used to transfer data between memory and the 
microprocessor. 

Debugging: (8) Testing a program to uncover possible errors. 

Decimal: (1) A number system based on a system of ten digits; the 
"normal" numbering system used by humans. 

Decrement: (2) To make smaller by a value of one. 

Descriptor: (6) A three-byte set of data giving a string's length and 
its location. 

Disassembler: (2) A program that changes object code into assembly 
code to allow inspection of a program. 

Disassemble: (2) To change object code into assembly code. Similar 
to a LIST in BASIC. 

Dynamic string: (6) A string that must be placed into memory after 
being received or calculated. 

Effective address: (2) The address used by the processor to handle 
data when executing an instruction. It may differ from the instruction ad- 
dress (or "operand") because of indexing or indirect addressing. 

Event flag: (7) A flag that signals that some event has happened. 

Execute: (1) To perform an instruction. 



GLOSSARY 



367 



File: (8) A collection of data stored on some external device. 

Flag: (3) An on/off indicator that signals some condition. 

Floating accumulator: (7) A group of memory iocations used by BASIC 
to perform calculations on a number. 

Garbage collection: (6) A BASIC process in which active strings are 
gathered together and inactive strings are discarded. On some computers 
this can be quite time consuming. 

Increment: (2) To make larger by a value of one. 

Index: (2) To change an address by adding the contents of an index 
register. 

Index register: (2) The X or Y registers, which may be used for chang- 
ing effective addresses. 

Indirect address: (5) An addressing scheme whereby the instruction 
contains the location of the actual address to be used; an address of an 
address. 

Instruction: (1 ) An element of a program that tells the processor what 
to do. 

Interrupt: (1) An event that causes the processor to leave its normal 
program so that some other program takes control, usually temporarily. 

Interrupt enable register: (7) A location within an lA chip that deter- 
mines whether or not a selected event will cause an interrupt. 

Interrupt flag: (7) A signal within the lA indicating that a certain event 
has requested that an interrupt take place. 

Interrupt flag register: (7) A location within the lA where interrupt 
events can be detected and turned off if desired. 

Interrupt source: (7) The particular event that caused an interrupt. 
Since many things can do this, it's usually necessary to identify the specific 
source of the interrupt. 

Kernal: (2) Commodore's operating system. 

Label, symbolic address: (8) A name identifying a memory location. 

Latch: (7) A flag that "locks in." 

Load: (1) To bring information from memory into the processor. A 
load operation is a copying activity; the information still remains in memory. 

Logical file number: (8) The identity of a file as used by the program- 
mer. 

Logical operator: (3) An operation that affects individual bits within a 
byte: AND, ORA, and EOR. 

Logical shift or rotate: (4) A shift that does not preserve the sign of 
a signed number. 

Machine code: (1) Instructions written in machine language. 

Machine language: (1) The set of commands that allow you to give 
instructions to the processor. 



368 MACHINE LANGUAGE FOR COMMODORE MACHINES 



Machine language monitor: (1 ) A program that allows communication 
with the computer in a manner convenient for machine language pro- 
gramming. 

Memory: (1 ) The storage used by a computer; every location is iden- 
tified by an address. 

Memory mapped: (1) Circuits that can be reached by the use of a 
niemoiy address, even though they are not used for storage or memory 
purposes. 

Memory page: (5) A set of 256 locations in memory, all of whose 
addresses have the same "high byte." 

Microcomputer: (1) A computer system containing a microprocessor, 
memory, and input/output circuits. A computer built using microchips. 

Microprocessor: (1) The central logic of a microcomputer, containing 
logic and arithmetic. A processor built on a microchip. 

Monitor: (1) A program that allows the user to communicate with the 
computer. Alternatively, a video screen device. 

Non-maskable interrupt, NMI: (7) A type of interrupt that cannot be 
disabled. 

Non-symbolic assembler: (2) An assembler in which actual addresses 
must be used. 

Object code: (1) The machine language program that will run in the 
computer. 

Octothorpe: (2) Sometimes called a numbers sign, a pounds sign, a 
hash mark. The "#" symbol. 

Operand: (1) The part of an instruction following the op code that 
usually signals where in memory the operation is to take place. 

Operating system: (1) A set of programs with a computer that takes 
care of general work such as input/output, timing, and so on. 

Operation code, op code: (1) The part of an instruction that says 
what to do. 

Overflow: (3) Condition caused by an arithmetic operation generating 
a result that is too big to fit in the space provided. 

Pointer: (6) An address held in memory, usually in two bytes. 

Processor status word, status register: (3) A processor register that 
holds status flags. 

Pull: (7) To take something from the stack. 

Push: (7) To put something on the stack. 

Random access memory, RAM: (1 ) The part of a computer's memory 
where information can be stored and recalled. 

Read: (1) To obtain information from a device. 

Read only memory, ROM: (1 ) The part of a computer's memory where 
fixed information has been stored. New information cannot be stored in a 
ROM; it is preprogrammed. 



GLOSSARY 



369 



Register: (1) Location within a processor where information can be 
held temporarily. 

Screen editing: (1) The ability to change the screen of a computer 
and cause a corresponding change in memory. 

Screen memory: (2) The part of a computer holding the information 
displayed on the screen. Changing screen memory will change the screen; 
reading screen memory will reveal what is on the screen. 

Selected: (1) A chip or device that has been signaled to participate 
in a data transfer. If the chip or device has not been selected, it will ignore 
data operations. 

Seif-modifying: (7) A type of program that changes itself as it runs. 
Rare, and not always considered good programming practice. 

Signed number: (3) A number that holds a value that may be either 
positive or negative. 

Source code: (1) Instructions written in assembly language; usually, 
the first code written by the programmer before performing an assembly. 

Stacl<: (7) A temporary, or "scratch pad," set of memory locations. 

Status register, processor status word: (3) Within the processor, a 
register that holds status flags. 

Store: (1) To transfer information from the processor to memory. The 
store operation is a copying activity: the information still remains in the 
processor. 

Subroutine: (2) A set of instructions that can be called up by another 
program. 

Symbolic address, label: (7) A name identifying a memory location. 

Symbolic assembler: (2) An assembler in which symbolic addresses 
may be used. This is more powerful than a non-symbolic assembler. 

Testable flag: (3) A flag that can be tested by means of a conditional 
branch instruction. 

Two's complement: (3) A method of representing negative numbers. 
With single byte numbers, - 1 would be represented by $FF. 

Unsigned number: (3) A number that cannot have a negative value. 

Write: (1) To send information to a device. 

Zero page: (5) The lowest 256 locations in memory. Locations whose 
addresses begin with hexadecimal $00. . . 



Index 



A, X, and Y data registers, 9, 11, 

46, 47, 142 
Absolute addressing, 148 
Absolute indexed mode, 77-78 
Absolute indirect, 149 
Absolute mode, 75-76 
Accumulator addressing, 148 
Accumulator mode, 74 
ADC, Add memory to accumulator 

with carry, 149 
Addition, 58-60 
Address, defined, 3 
Address bus, 3-5 
Addressing modes, 72-89, 

148-149 
Algorithms: 

decimal to hexadecimal, 7 

hexadecimal to decimal, 7 
AND, "AND" memory with 
accumulator, 121, 149 
ASCII, 25, 50, 249-250 
ASL, Shift left one bit (memory or 

accumulator), 61-62, 149 
Assemblers: 

nonsymbolic, 27 

symbolic, 143-144 

BASIC: 
breaking into, 124-125 
infiltrating, 122-124 



linking with, 30-31 

machine language exchanging 

data, 104-108 
memory layout, 92-102 
variables, 102-105 
BCC, Branch on carry clear, 87, 
149 

BCS, Branch on carry set, 149 
BEQ, Branch on result zero, 149 
Binary, defined, 2 
Bit, defined, 2 

BIT, Test bits in memory with 

accumulator, 142, 149 
Bit map mode on the 6566/6567, 

328-330 
BMI, Branch on result minus, 149 
BNE, Branch on result not zero, 

149 

BOS, Bottom of string, 94-95 
BPL, Branch on result plus, 149 
Branches and branching, 79-80 
Branch instructions, 141 
BRK, Force-break, 72, 115, 116, 
142, 143, 149, 279 

Bus: 

address, 4-5 

control, 5 

defined, 3 

see also Data bus 
BVC, Branch on overflow clear, 150 



371 



372 MACHINE LANGUAGE FOR COMMODORE MACHINES 



BVS, Branch on overflow set, 1 50 
Bytes, multiple, 58 

C flag, 42, 45, 46 

Character display mode of the 

6566/6567, 325-327 
Character sets, 242-250 
Chip information, 293-356 
6520 (PIA) Peripheral interface 

adaptor, 294-298 
6522 (VIA) Versatile interface 
adaptor, 309-318 

6525 Tri-port interface, 352-356 

6526 (CIA) Complex interface 
adaptor, 318-325 

6545-1 (CRTC) CRT controller, 

299-304 
6560 (VIC) video interface chip, 

304-309 
6566/6567 (VIC II) chip 

specifications, 325-340 
6581 (SID) Sound interface 
device, chip specifications, 
340-351 
CHKIN subroutine, 136 
CHKOUT subroutine, 133, 134 
CHRGET subroutine, 122-123, 
124 

CHRGOT subroutine, 123, 

124-125 
CHROUT subroutine, 25, 133 
CIA chip, 120 
CLC, Clear carry flag, 150 
CLD, Clear decimal mode, 150 
CLI, clear interrupt disable bit, 118 
Clock speed, 132 
CLOSE, 134 

CLRCHN subroutine, 133, 135, 

136, 137 
CLV, Clear overflow flag, 150 
CMP, Compare memory and 

accumulator, 150 



Color codes of the 6566/6567, 340 
Commodore computers, 

characteristics of, 156-166 
Compare, 141 

Comparing numbers, 61-62 
Complex interface adaptor 6526, 

318-325 
Control bus, 5 

CPX, Compare memory and index 
X, 150 

CPY, Compare memory and index 
Y, 150 

Data bus, 4-5 
see also Bus 
Data exchange, BASIC machine 

language, 104-108 
Debugging, 143 

DEC, Decrement memory by one, 
150 

Decimal notation to hexadecimal, 
7-8 

DEX, Decrement index X by one, 
150 

DEY, Decrement index Y by one, 
150 

Disassembler, checking the, 
29-30 

Disk user's guide, 357-364 
Division by two, 63-64 
Do nothing insruction, 72-74 
Dynamic string, 94 

Effective address, 32 
End of BASIC, 92-93 
Envelope rates of the 6581 , 347 
EOA, end of arrays, 93 
EOR, exclusive or, 47, 48, 49, 121, 
150 

EOR instruction, 87 
Exercises, 11-13, 52-54, 
84-88, 252-278 



INDEX 



373 



adding a command, 125-126, 

256, 271-273 
addition, 263-264 
for Commodore CI 28, 257-276 
file transfer, 274-276 
input, 263 

interrupt, 119-120, 254-255, 

270-271 
loops, 262-263 
output, 273-274 
print, 26-27, 259-262 
screen manipulation, 265-266 
Extended color mode of the 6566/ 

6567, 328 

File transfer program, 138-141 
Flags, 40-46 

Floating point variables, 103 
Free memory, 94-95 

GETIN, Gets an ASCII character, 

25, 133 
Glossary, 365-369 

Handshaking, 318-319 
Hexadecimal notation, 5-6 
Hexadecimal notation to decimal, 
6-7 

lA, Interface adaptor chips, 9, 50, 

120-122, 142 
lER, Interrupt enable register, 122 
IFR, Interrupt flag register, 121 
Immediate addressing, 148 
Immediate mode, 74-75 
Implied addressing, 148 
Implied mode, 72-74 
INC, Increment memory by one, 74, 

150 

Increment and decrement 

instructions, 141 
Indexed absolute addressing, 148 



Indexed indirect addressing, 149 
Indexed indirect mode, 83-84 
Indexed zero page addressing, 148 
Indexing modes: 

absolute, 77-78 

indirect, 81-82 

zero page, 78 
Index registers, 33 
Indirect indexed addressing, 149 
Indirect indexed mode, 81-82 
Infiltrating BASIC, 122-124 
Input, 50-52, 133 
Input: 

GETIN, 50-51 

switching, 136-137 
INSj increment, 72 
Instruction execution, 10-11 
Instruction set, 141-142, 147 

alphabetic sequence, 149-151 
Integer variables, 104 
Interface adaptor chips, 9, 50, 

120-122, 142 
Interrupt enable register, 122 
Interrupt flag register, 121 
Interrupt processing, 40 
Interrupt request, 115 
INX, Increment index X by one, 150 
INY, Increment index Y by one, 150 
IRQ, Interrupt request, 115, 
117-118 

JMP, Jurhp to new location, 

80-81, 141-142, 150 
JSR, Jump to new location saving 

return address, 114-115, 150 
Jumps in indirect mode, 80-81 
Jump subroutine, 142 

Kernal, 24 

Kernal subroutines: 

CHKIN, 136 

CHROUT, 25, 133, 134 



374 MACHINE LANGUAGE FOR COMMODORE MACHINES 



CLRCHN, 136 
GETIN, 51 
STOP, 52 

LDA, Load accumulator with 

memory, 150 
LDX, Load index X with memory, 

150 

LDY, Load index Y with memory, 

150 
Light pen, 335 
LOAD, 100-101 

Logical and arithmetic routines, 141 
Logical operators, 47-50 
Loops, 32-34, 262-263 
LSR, Shift one bit right (memory or 
accumulator), 63-64, 150 

Machine language and BASIC 
exchanging data, 104-108 
Machine language linking with 

BASIC, 30-31 
Machine language monitor SAVE, 

99-100 
Memory, free, 94-95 
Memory contents: 
changing, 17 
displaying, 17 
Memory elements, 8-9 
Memory interface of the 6566/6567, 

337-340 
Memory layout, BASIC, 92-102 
Memory maps: 
B series, 203-212 
CBM 8032, 179-180 
Commodore PLUS/4 "TED" chip, 

201-203 
Commmodore 64, 191-200 
Commodore 128, 213-230 
FAT-40 6545 CRT, controller, 

179-180 
"Original ROM" PET, 168-172 



Upgrade and BASIC 4.0 systems, 

172-179 
VIC 20, 181-187 
VIC 6522 usage, 189-190 
VIC 6560 chip, 188 
Microprocessor chips, 650X, 3-4 
MLM, Machine language monitors, 
14, 284 

MLM commands, 16-17, 99-100 

.G command, 1 7 

.M command, 16 

.R command, 16 

Save command, 99-100 

.X command, 16 
Modes: 

absolute indexed, 77-78 

addressing, 72-89 

ail of zero page, 78 

indexed, indirect, 83-84 

indirect, indexed, 81-82 

jumps in indirect, 80-81 

no address, 72-74 

no address accumulator, 74 

not quite an address, 74-75 

relative address, 79-80 

single address, 75-76 

zero page, 76-78 
Monitors: 

basic, 14 

display, 15 

extensions, 27-29 

machine language (MLM), 
14-15, 290-291 

machine language SAVE, 
99-100 

Multi-color character mode of the 

6566/6567, 327 
Multiplication, 62-63 
by two, 61-62 

N flag, 42-43, 45, 46 
Non-maskable interrupt (NMI), 115, 
118 



INDEX 



375 



NOP, No operation, 72-74, 85, 
150 

NOP BRK, No operation, breal<, 

false interrupt, 142 
Numbers: 

comparing, 61-62 

signed, 43-44, 58 

unsigned, 58 
Numeric variables, 104 

OPEN, 133-134 

ORA, "OR" memory with 

accumulator, 47, 48, 49, 121, 
150 
Output, 133 
controlling, 24-36 
examples of, 135-136 
switching, 133-135 
Overflow, 44 

PC, Program control register, 9 
PEEK, 5, 104 

PHA, Push accumulator on stack, 

113, 150 
PHP, Push processor status on 

stack, 114, 150 
PIA, Peripheral interface adaptor 

6520, 120, 294-298 
PLA, Pull accumulator from stack, 

113, 114, 150 
PLP, Pull processor status from 

stack, 114, 150 
Pointers, fixing, 102 
POKE, 5, 26, 104 
Program: 
entering a, 18-19 
running a, 30 
Program Counter, 9-11, 149 
Programming model, 151 
Programming projects, 11-13, 

52-54, 84-88, 252-278 
adding a command, 125-126, 

256 



interrupt, 119-120, 254-255 

print, 26-27 
Programs, file transfer, 138-141 
Pull information, 142 
Push information, 142 
Push processor status, 114 

RAM, Random access memory, 8 
Register map of the 6566/6567, 

338-339 
Registers, 9-10, 18 

A, X, and Y, 9, 1 1 , 46, 47 

index, 33 

status, 45-46 
Relative addressing, 148-149 

mode, 79-80 
ROL, Rotate one bit left (memory or 

accumulator), 62, 150 
ROM, Read only memory, 8-9 

link, 80-81 
ROR, Rotate one bit right (memory 

or accumulator), 63-64, 150 
Rotate, comments, 64-65 
RTI, Return from interrupt, 115, 150 
RTS, Return from subroutine, 65, 

114-115, 151 
RUN STOP key, 51-52 

6502 Instruction set, 147 

6509 Instruction set, 147 

6510 Instruction set, 147 
6520 (PIA) Peripheral interface 

adaptor, 294-298 
6522 (VIA) Versatile interface 
adaptor, 309-318 

6525 Tri-port interface, 352-356 

6526 (CIA) Complex interface 
adaptor, 318-325 

6545-1 (CRTC) CRT controller, 

299-304 
6560 (VIC) Video interface chip, 

304-309 



376 



MACHINE LANGUAGE FOR COMMODORE MACHINES 



6566/6567 (VIC II) chip 

specifications, 325-340 
6581 (SID) Sound interface device, 

chip specifications, 340-351 
7501 Insruction set, 147 
SAVE, 34, 141 

stopgap, 34-35 
SBC, Subtract memory from 

accumulator with borrow, 151 
Screen codes, 242-250 
Screen manipulations, 84-88 
Screen memory address, 21 
SEC, Set carry flag, 1 51 
SEP, Set decimal mode, 151 
SEI, Set interrupt disabler status, 

118, 151 
Shift, comments on, 64-65 
Shift and rotate instructions, 

61-63, 74, 141 
Signed numbers, 43-44, 58 
Single address mode, 75-76 
SOA, Start of arrays, 93 
SOB, Start of BASIC, 92 
Sound interface device (SID) chip 

specification 6581, 340-351 
SOV, Start of variables, 93, 

97-102 
SP, Stack pointer register, 9 
SR, Status register, 9 
STA, Store accumulator in memory, 

151 

Stack, 112-115 
Status register, 45-46 

Stop, 25, 51-52 

Stopgap save command, 34-35 

Storage, temporary, 112-115 

String variables, 103 

STX, Store index X in memory, 151 

STY, Store index Y in memory, 151 

Subroutines: 

CHROUT, 25 

GETIN, 25, 50-51 



KERNAL, 24 

prewritten, 24-25 

STOP, 25, 51-52 
Subtraction, 60-61 
Supermen program, 27, 284-289 
Supermon+ program, 290-291 
Symbolic assemblers, 143-144 
SYS, Go to the address supplied, 
116 

TAX, Transfer accumulator to index 

X, 113, 151 
TAY, Transfer accumulator to index 

Y, 72, 113, 151 
Testable flags, 40-45 
Time of day clock, 321 
Timing, machine language program, 

132-133 
TOM, Top of memory, 93-94 
Tri-port interface 6525, 352-356 
TSX, Transfer stack pointer to 

index X, 151 
Two's complement, 43 
TXA, Transfer index X to 

accumulator, 151 
TXS, Transfer index X to stack 

register, 151 
TYA, Transfer index Y to 

accumulator, 151 

Uncrashing techniques, 280-281 

Unsigned numbers, 58 

USR, Go to a fixed address and 
execute machine code there as 
a subroutine, 116-117 

Variables, 102-105 

V flag, 44, 45, 46 

VIA, Versatile interface adaptor, 

120-121 
VIC II chip specifications 6566/ 

6567, 325-340 



INDEX 



377 



(VIC) Video interface chip 6560, Zero page addressing, 148 

304-309 Zero page mode, 76-78 

indexed, 78 

Wedge, 122-124 Z flag, 40-41, 45, 46 

program, 124-125 



Pull up a chair and sit down with Jim Butterfield — the Commodore guru 
himself — and get the answers to all your questions about machine lan- 
guage with . . . 

Machine Language for the 
Commodore 64, 128, and Other 
Commodore Computers 

Revised & Expanded Edition /by Jim Butterfield 

Authored by the world- renowned expert on all facets of the Commodore, 
this comprehensive tutorial introduces programmers of all levels to the 
principles of machine language — what it is, how it works, and how to 
program with it. With speed and versatility, you'll share in Butterfield's 
vast experience as you: 

• Learn-by-doing — with easy-to-follow, step-by-step instructions, exam- 
ples, and exercises 

• Uncover the critical elements to understanding machine language, 
machine architecture, and machine language tools 

• Master principles of good coding practices — for more efficient and 
effective programming 

• Explore the inner workings of the Commodore, write and enter a simple 
program, learn the details behind output, flags, logic, input, subrou- 
tines, address modes, and more! 

Not only an excellent tutorial, it's an invaluable resource you'll refer to 
again and again! 

TABLE OF CONTENTS 

First Concepts / Controlling Output / Flags, Logic, and Input / Numbers, 
Arithmetic, and Subroutines / Address Modes / Linking BASIC and 
Machine Language / Stack, USE, Interrupt, and Wedge / Timing, Input/ 
Output, and Conclusion / Appendix A: The 6502/6510/6509/7501 Instruc- 
tion Set / Appendix B: Some Characteristics of Commodore Machines / 
Appendix C: Memory Maps / Appendix D: Character Sets / Appendix E: 
Exercises for Alternative Commodore Machines / Appendix F: Floating 
Point Formats / Appendix G: Uncrashing / Appendix H: A Do-It- Yourself 
Supermen / Appendix I: lA Chip Information / Appendix J: Disk User's 
Guide / Index 



I 'l21898"66417' 4 



Cover illustration by David Joly 
Cover Design by Ben Santora 

A Brady Book • Published by Prentice Hall Press • New York 



ISBN 0-fl=13D3-bb4-l